Skip to content

Commit

Permalink
use Deno FileDescriptor for CSV export
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanfallon committed Jul 1, 2024
1 parent c5db1db commit 8f1c885
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 13 deletions.
42 changes: 41 additions & 1 deletion api/src/lib/file/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,47 @@
import { join } from "@/lib/path/index.ts";

let tmpDir: string;

/**
* Create a new temporary directory if it doesn't exist yet.
* Otherwise, return the existing one from the tmpDir variable.
*/
export function getTmpDir(): string {
if (!tmpDir) {
tmpDir = Deno.makeTempDirSync();
const parts = Deno.makeTempDirSync().split("/");
parts.pop();
tmpDir = "/" + join(...parts);
}

return tmpDir;
}

export type OpenFileOptions = Deno.OpenOptions;
export type OpenFileDescriptor = Deno.FsFile;

/**
* Create and open a file for reading and writing.
*
* @example
* const fd = await open("example.txt", { read: true, write: true });
* fd.close();
*
* @example
* const df = await open("example.txt", { write: true, append: true });
* await fd.write(new TextEncoder().encode("Hello, World!"));
* await fd.write(new TextEncoder().encode("Hello, World!"));
* fd.close();
*
* @param filepath
* @param options
* @returns
*/
export function open(
filepath: string,
options: OpenFileOptions = { read: true },
): Promise<OpenFileDescriptor> {
return Deno.open(filepath, {
...options,
create: true,
});
}
34 changes: 22 additions & 12 deletions api/src/pdc/services/trip/actions/file/BuildFile.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FileHandle, open, Stringifier, stringify } from "@/deps.ts";
import { Stringifier, stringify } from "@/deps.ts";
import { provider } from "@/ilos/common/index.ts";
import { getTmpDir } from "@/lib/file/index.ts";
import { getTmpDir, open, OpenFileDescriptor } from "@/lib/file/index.ts";
import { logger } from "@/lib/logger/index.ts";
import { join } from "@/lib/path/index.ts";
import { v4 as uuidV4 } from "@/lib/uuid/index.ts";
Expand All @@ -19,6 +19,8 @@ import { BuildExportAction } from "../BuildExportAction.ts";

@provider()
export class BuildFile {
private readonly batchSize = 1000;

constructor() {}

public async buildCsvFromCursor(
Expand All @@ -28,9 +30,14 @@ export class BuildFile {
isOpendata: boolean,
): Promise<string> {
// CSV file
const { filename, tz } = this.cast(params.type, params, date);
const { filename, tz } = this.cast(
params.type || "opendata",
params,
date,
);
const filepath = join(getTmpDir(), filename);
const fd = await open(filepath, "a");
const fd = await open(filepath, { write: true, append: true });
logger.debug(`Exporting file to ${filepath}`);

// Transform data
const stringifier = this.configure(fd, params.type);
Expand All @@ -39,7 +46,7 @@ export class BuildFile {
try {
let count = 0;
do {
const results = await cursor.read(10);
const results = await cursor.read(this.batchSize);
count = results.length;
for (const line of results) {
stringifier.write(normalizeMethod(line, tz));
Expand All @@ -49,15 +56,18 @@ export class BuildFile {
// Release the db, end the stream and close the file
await cursor.release();
stringifier.end();
await fd.close();
fd.close();

logger.debug(`Finished exporting file: ${filepath}`);

return filepath;
} catch (e) {
await cursor.release();
await fd.close();
logger.error(e.message, e.stack);
stringifier.end();
fd.close();

logger.error(e.message);
logger.debug(e.stack);
throw e;
}
}
Expand All @@ -76,17 +86,17 @@ export class BuildFile {
}

private configure(
fd: FileHandle,
fd: OpenFileDescriptor,
type = "opendata",
): Stringifier {
const stringifier = stringify({
delimiter: ";",
header: true,
columns: BuildExportAction.getColumns(type),
cast: {
boolean: (b: Boolean): string => (b ? "OUI" : "NON"),
boolean: (b: boolean): string => (b ? "OUI" : "NON"),
date: (d: Date): string => d.toISOString(),
number: (n: Number): string => n.toString().replace(".", ","),
number: (n: number): string => n.toString().replace(".", ","),
},
quoted: true,
quoted_empty: true,
Expand All @@ -96,7 +106,7 @@ export class BuildFile {
stringifier.on("readable", async () => {
let row: string;
while ((row = stringifier.read()) !== null) {
await fd.appendFile(row, { encoding: "utf8" });
await fd.write(new TextEncoder().encode(row + "\n"));
}
});

Expand Down

0 comments on commit 8f1c885

Please sign in to comment.