<commit_before>import fs from 'fs';
import path from 'path';
import readline from 'readline';
import { Tail } from 'tail';

const serverWatchingFile = 'ak-server.iswatching';
const serverReadyForJsonFile = 'ak-eep-out-json.isfinished';
const watchedJsonFileName = 'ak-eep-out.json';
const watchedLogFileName = 'ak-eep-out.log'; // TODO: CHANGE TO ak-eep-out.log
const writtenCommandFileName = 'ak-eep-in.commands';
const writtenEventFileName = 'ak-eep-in.event';

export default class FileOperations {
  private dir: string;
  private jsonFileWatcher: fs.FSWatcher;
  private logTail: Tail;
  private onJsonUpdate: (jsonText: string) => void;
  private onLogLine: (line: string) => void;

  constructor() {}

  public reInit(dir: string, callback: (err: string, dir: string) => void): void {
    this.dir = path.resolve(dir);

    if (this.logTail) {
      this.logTail.unwatch();
    }
    if (this.jsonFileWatcher) {
      this.jsonFileWatcher.close();
    }
    this.onJsonUpdate = (jsonText: string) => {
      console.log('Received: ' + jsonText.length + ' bytes of JSON');
    };
    this.onLogLine = (line: string) => {
      console.log(line);
    };

    fs.stat(this.dir, (err, stats) => {
      if (!err && stats.isDirectory()) {
        this.attachAkEepOutJsonFile();
        this.attachAkEepOutLogFile();
        this.createAkServerFile();
        callback(null, this.dir);
      } else {
        callback('No such directory: ' + this.dir, null);
      }
    });
  }

  private deleteFileIfExists(file: string): void {
    try {
      fs.unlinkSync(file);
    } catch (err) {
      /* ignored */
    }
  }

  private attachAkEepOutJsonFile(): void {
    const jsonFile = path.resolve(this.dir, watchedJsonFileName);
    const jsonReadyFile = path.resolve(this.dir, serverReadyForJsonFile);

    // First: delete the file from EEP, so EEP will know we are ready
    this.deleteFileIfExists(jsonReadyFile);

    // Watch in the directory, if the file is recreated
    this.jsonFileWatcher = fs.watch(this.dir, {}, (eventType: string, filename: string) => {
      // If the jsonReadyFile exists: Read the data and remove the file
      if (filename === serverReadyForJsonFile && fs.existsSync(jsonReadyFile)) {
        // EEP has written the JsonFile for us, so let's read it.
        fs.readFile(jsonFile, { encoding: 'latin1' }, (err, data) => {
          if (err) {
            console.log(err);
            this.deleteFileIfExists(jsonReadyFile);
          } else {
            this.onJsonUpdate(data);
          }
        });
        // Last: delete the file from EEP, so EEP will know we are ready
        this.deleteFileIfExists(jsonReadyFile);
      }
    });
  }
<commit_msg>remove JsonReady file *after* reading data<commit_after>import fs from 'fs';
import path from 'path';
import readline from 'readline';
import { Tail } from 'tail';

const serverWatchingFile = 'ak-server.iswatching';
const serverReadyForJsonFile = 'ak-eep-out-json.isfinished';
const watchedJsonFileName = 'ak-eep-out.json';
const watchedLogFileName = 'ak-eep-out.log'; // TODO: CHANGE TO ak-eep-out.log
const writtenCommandFileName = 'ak-eep-in.commands';
const writtenEventFileName = 'ak-eep-in.event';

export default class FileOperations {
  private dir: string;
  private jsonFileWatcher: fs.FSWatcher;
  private logTail: Tail;
  private onJsonUpdate: (jsonText: string) => void;
  private onLogLine: (line: string) => void;

  constructor() {}

  public reInit(dir: string, callback: (err: string, dir: string) => void): void {
    this.dir = path.resolve(dir);

    if (this.logTail) {
      this.logTail.unwatch();
    }
    if (this.jsonFileWatcher) {
      this.jsonFileWatcher.close();
    }
    this.onJsonUpdate = (jsonText: string) => {
      console.log('Received: ' + jsonText.length + ' bytes of JSON');
    };
    this.onLogLine = (line: string) => {
      console.log(line);
    };

    fs.stat(this.dir, (err, stats) => {
      if (!err && stats.isDirectory()) {
        this.attachAkEepOutJsonFile();
        this.attachAkEepOutLogFile();
        this.createAkServerFile();
        callback(null, this.dir);
      } else {
        callback('No such directory: ' + this.dir, null);
      }
    });
  }

  private deleteFileIfExists(file: string): void {
    try {
      fs.unlinkSync(file);
    } catch (err) {
      /* ignored */
    }
  }

  private attachAkEepOutJsonFile(): void {
    const jsonFile = path.resolve(this.dir, watchedJsonFileName);
    const jsonReadyFile = path.resolve(this.dir, serverReadyForJsonFile);

    // First: delete the file from EEP, so EEP will know we are ready
    this.deleteFileIfExists(jsonReadyFile);

    // Watch in the directory, if the file is recreated
    this.jsonFileWatcher = fs.watch(this.dir, {}, (eventType: string, filename: string) => {
      // If the jsonReadyFile exists: Read the data and remove the file
      if (filename === serverReadyForJsonFile && fs.existsSync(jsonReadyFile)) {
        // EEP has written the JsonFile for us, so let's read it.
        fs.readFile(jsonFile, { encoding: 'latin1' }, (err, data) => {
          // Delete the file from EEP, so EEP will know we are ready
          this.deleteFileIfExists(jsonReadyFile);
          if (err) {
            console.log(err);
          } else {
            this.onJsonUpdate(data);
          }
        });
      }
    });
  }

{'fraction_non_alphanumeric': 0.13108334887190007, 'fraction_numerical': 0.00037292560134253216, 'mean_word_length': 2.8673395818312906, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '920540', 'n_tokens_mistral': 1700, 'n_tokens_neox': 1673, 'n_words': 421}