【问题标题】:How to use fs.watch in a graphQL controller如何在 graphQL 控制器中使用 fs.watch
【发布时间】:2021-11-05 07:58:48
【问题描述】:

我正在尝试在 graphQL 控制器中使用 fs.watch() 来观察测试输出 json 文件中的变化,并将测试是否通过他们提出的解决方案返回给用户。

现在,我的突变总是得到null 的答案。 所有测试都运行正常,output.json文件也正确写入,但是控制器函数在返回正确值之前返回null

我的控制器如下:

import { Context } from "../typescript/types";
import TestModel from "../models/TestModel";

const fs = require("fs-extra");

interface InputSolution {
  userId: string;
  exerciseId: string;
  testIDs: string[];
  solution: string;
}

export default class SandboxController {
  async postSolution(
    parent: any,
    args: { input: InputSolution },
    context: Context
  ) {

    // 1. delete all files in src and spec, and the output json file
    try {
      await fs.emptyDir("./userCode/src");
      await fs.emptyDir("./userCode/spec");
      console.log("success!");
    } catch (err) {
      console.error(err);
    }

    // 2. create new files for: the function that is tested, and the tests
    const tests = await TestModel.find()
      .where("_id")
      .in(args.input.testIDs)
      .exec();

    try {
      await fs.writeFile("./userCode/src/solution.js", args.input.solution);
      tests.forEach(async (test, index) => {
        await fs.writeFile(
          `./userCode/spec/test${index}.spec.js`,
          test.content
        );
      });
      console.log("success!");
    } catch (err) {
      console.error(err);
    }

    // 3. create the flag file to show changes were made
    try {
      await fs.writeFile(
        "./userCode/flag.txt",
        args.input.exerciseId + " - " + args.input.userId
      );
      console.log("success!");
    } catch (err) {
      console.error(err);
    }


    // 4. Watch the output file
    fs.watch(
      "./userCode/flag.txt",
      async (eventType: string, filename: string) => {
        console.log(`event type is: ${eventType}`);

        const json = await fs.readFile(
          "./userCode/testLogs/output.json",
          "utf8"
        );

        const output: any = json ? JSON.parse(json) : null;

        if (
          output &&
          (output.numTotalTestSuites > 0 || output.numTotalTests > 0)
        ) {
          //
          console.log("numTotalTestSuites", output.numTotalTestSuites);

          if (output.numFailedTestSuites === 0 && output.numFailedTests === 0) {
            console.log("all good");
            return [{ testId: "12", passed: true }];
          } else {
            console.log("tests failed", output.numFailedTestSuites);
            return [{ testId: "12", passed: false }];
          }
          //
        } else {
          return [{ testId: "12", passed: false }];
        }
      }
    );
  }
}

任何帮助将不胜感激。

【问题讨论】:

    标签: node.js graphql fs


    【解决方案1】:

    在这里回答我自己的问题:这是我使用的一个包装函数,使用 Promises,以确保 fs.watch 将运行正确的时间(即,直到满足条件),并且能够等待它。

    function watchOnceUntil(
      url: string,
      condition: () => boolean,
      timeout: number
    ) {
      const startTime = Date.now();
      const promise = new Promise((resolve, reject) => {
        const watcher = fs.watch(url, (eventType: string, filename: string) => {
          const result = condition(); // boolean
          if (result) {
            watcher.close();
            resolve({ eventType, filename });
          } else if (Date.now() - startTime > timeout) {
            watcher.close();
            reject();
          }
        });
      });
      return promise;
    }
    

    我的控制器现在看起来像第 4 步:

        // 4. Watch the output file
        await watchOnceUntil(
          "./userCode/testLogs/output.json",
          () => {
            const json = fs.readFileSync("./userCode/testLogs/output.json", "utf8");
    
            const output: FullJestOutput | null = json ? JSON.parse(json) : null;
            if (output === null) return false;
            return output.numTotalTestSuites > 0 || output.numTotalTests > 0;
          },
          10000
        );
    
        const json = fs.readFileSync("./userCode/testLogs/output.json", "utf8");
    
        const output: FullJestOutput | null = json ? JSON.parse(json) : null;
    
        const result: TestResult | null = !output
          ? null
          : {
              success: output.success,
              testResults: output.testResults,
            };
    
        return result;
    

    【讨论】:

      猜你喜欢
      • 2018-10-04
      • 2022-07-06
      • 1970-01-01
      • 2018-04-19
      • 2017-04-29
      • 1970-01-01
      • 2019-10-22
      • 2022-01-03
      • 1970-01-01
      相关资源
      最近更新 更多