Skip to content

Commit

Permalink
feat: add public findAll method
Browse files Browse the repository at this point in the history
  • Loading branch information
DIY0R committed Aug 26, 2024
1 parent 379293e commit d237fa4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 20 deletions.
20 changes: 16 additions & 4 deletions lib/graph/file.graph.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
FileGraphAbstract,
IFindVertex,
IPredicate,
IUpdater,
IVertex,
Expand Down Expand Up @@ -44,12 +45,23 @@ class FileGraphIml implements FileGraphAbstract {
);
}

public findOne<T extends object>(
public async findOne<T extends object>(
predicate: IPredicate<T>,
): Promise<IVertex<T> | null> {
return this.storageFile.searchLine(predicate);
}

public async findAll<T extends object>(
predicate: IPredicate<T>,
): Promise<IVertex<T>[]> {
const vertices = [];
const findVertex: IFindVertex<T> = vertex => {
if (predicate(vertex)) vertices.push(vertex);
};
await this.storageFile.searchLine(findVertex);
return vertices;
}

public createArc(
sourceVertexId: uuidType,
targetVertexId: uuidType,
Expand Down Expand Up @@ -84,8 +96,8 @@ class FileGraphIml implements FileGraphAbstract {
sourceVertexId: uuidType,
targetVertexId: uuidType,
): Promise<boolean> {
const targetVertexExists = await this.storageFile.searchLine(
v => v.id == sourceVertexId,
const targetVertexExists = await this.findOne(
vertex => vertex.id === sourceVertexId,
);
if (!targetVertexExists)
throw new Error(`Target vertex with ID "${targetVertexId}" not found`);
Expand All @@ -98,7 +110,7 @@ class FileGraphIml implements FileGraphAbstract {
updater: IPredicate<object> | IUpdater<object>,
): Promise<boolean> {
return this.asyncTaskQueue.addTask<boolean>(async () => {
const targetVertexExists = await this.storageFile.searchLine(
const targetVertexExists = await this.findOne(
vertex => vertex.id === targetVertexId,
);
if (!targetVertexExists)
Expand Down
24 changes: 9 additions & 15 deletions lib/graph/storage.file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { appendFile } from 'fs/promises';
import { finished } from 'stream/promises';
import readline from 'readline';
import { mergeVertices, uuid } from '../utils';
import { IPredicate, IUpdater, IVertex } from '../interfaces';
import { IFindVertex, IPredicate, IUpdater, IVertex } from '../interfaces';

export class StorageFile {
constructor(private readonly path: string) {}

Check warning on line 13 in lib/graph/storage.file.ts

View workflow job for this annotation

GitHub Actions / lint-and-test (20.x)

'path' is defined but never used
Expand All @@ -21,32 +21,31 @@ export class StorageFile {
}

public async searchLine<T extends object>(
predicate: IPredicate<T>,
predicate: IFindVertex<T> | IPredicate<T>,
): Promise<IVertex<T>> {
const fileStream = this.createLineStream();
const findVertex = await fileStream(async line => {
const fileStream = this.createLineStream(true);
return await fileStream(async line => {
const vertex = this.deserializer(line) as IVertex<T>;
if (predicate(vertex)) return vertex;
});
return findVertex;
}

public async updateLine<T extends object>(
updater: IPredicate<T> | IUpdater<T>,
): Promise<boolean> {
const tempPath = `${this.path}.${uuid()}.tmp`;
let updated = false;
const fileStream = this.createLineStream();
const fileStream = this.createLineStream(false);
const tempStream = createWriteStream(tempPath, { encoding: 'utf8' });
try {
await fileStream(async line => {
const vertex = this.deserializer(line) as IVertex<T>;
const updaterVertex = updater(vertex);
if (updaterVertex === true) return void (updated = true);
if (updaterVertex === true) return (updated = true);
if (typeof updaterVertex === 'object' && updaterVertex !== null) {
const newVertices = mergeVertices(vertex, updaterVertex);
tempStream.write(this.serializer(newVertices) + '\n');
return void (updated = true);
return (updated = true);
}
tempStream.write(line + '\n');
});
Expand All @@ -60,12 +59,7 @@ export class StorageFile {
await fsPromises.rename(tempPath, this.path);
return updated;
}
private async handleStream(tempStream, tempPath, destinationPath) {
await finished(tempStream);

await fsPromises.rename(tempPath, destinationPath);
}
private createLineStream() {
private createLineStream(canAbort: boolean) {
const fileStream = createReadStream(this.path, 'utf8');
const rl = readline.createInterface({
input: fileStream,
Expand All @@ -76,7 +70,7 @@ export class StorageFile {
try {
for await (const line of rl) {
const result = await read(line);
if (result) return result;
if (canAbort && result) return result;
}
} finally {
rl.close();
Expand Down
13 changes: 13 additions & 0 deletions lib/interfaces/graph.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ export abstract class FileGraphAbstract {
predicate: IPredicate<T>,

Check warning on line 61 in lib/interfaces/graph.interface.ts

View workflow job for this annotation

GitHub Actions / lint-and-test (20.x)

'predicate' is defined but never used
): Promise<IVertex<T> | null>;

/**
* Searches for vertices in the storage file that match the given predicate.
*
* This method retrieves all vertices that satisfy the condition specified by the `predicate` function.
*
* @template T The data type of the vertex, which must match the type of the object.
* @param {function(T): boolean} predicate - A function that takes a vertex as input and returns `true` if the vertex matches the search criteria, otherwise `false`.
* @returns {Promise<T[]>} A promise that resolves to an array of vertices that match the search criteria.
*/
public abstract findAll<T extends object>(
predicate: IPredicate<T>,
): Promise<IVertex<T>[]>;

/**
* Creates an arc (edge) from one vertex to another in the graph.
*
Expand Down
4 changes: 3 additions & 1 deletion lib/interfaces/params.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ export interface IVertex<T extends object> {
arcs: Array<uuidType>;
data: T;
}

export type IPredicate<T extends object> = (vertex: IVertex<T>) => boolean;
export type IUpdater<T extends object> = (
vertex: IVertex<T>,
) => IVertex<T> | object;
export type IFindVertex<T extends object> = (
vertex: IVertex<T>,
) => IVertex<T> | void;

0 comments on commit d237fa4

Please sign in to comment.