From a94bb8f1c5e22d392a74616fe80af4a8f347d54a Mon Sep 17 00:00:00 2001 From: arinaazmi Date: Tue, 26 Nov 2024 20:40:29 -0500 Subject: [PATCH] Validation and Syntax Fixes Fixes to the validation tester --- libs/checkpoint-firebase/src/index.ts | 25 +---- .../src/tests/checkpoints.int.test.ts | 93 ++----------------- libs/checkpoint-validation/package.json | 2 +- .../src/tests/firebase_initializer.ts | 77 ++++----------- 4 files changed, 29 insertions(+), 168 deletions(-) diff --git a/libs/checkpoint-firebase/src/index.ts b/libs/checkpoint-firebase/src/index.ts index 1ee4e3a8..f4119b65 100644 --- a/libs/checkpoint-firebase/src/index.ts +++ b/libs/checkpoint-firebase/src/index.ts @@ -228,21 +228,6 @@ export class FirebaseSaver extends BaseCheckpointSaver { "Failed to serialized checkpoint and metadata to the same type." ); } - - /* We want to store the following (taken from MongoDB implementation) - - checkpoint ID - - checkpoint type - - checkpoint (serialized) - - metadata (serialized)*/ - - /* SQLite implementation also stores the following - - parent checkpoint ID - - thread ID, - - checkpoint_ns, */ - - /* I believe the excess values are stored for debugging purposes (hunch) - I am going to store the excess values as well here */ - const data = { thread_id: thread_id, checkpoint_ns: checkpoint_ns, @@ -253,15 +238,11 @@ export class FirebaseSaver extends BaseCheckpointSaver { metadata: serializedMetadata }; - /* "thread_id", "checkpoint_ns", and "checkpoint_id" - form the "primary key" for this database */ const docKey = `${thread_id}_${checkpoint_ns}_${checkpoint.id}`; - /* Get a reference to the location in the database - where you want to store the data */ + const dataRef = ref(this.db, `${this.checkpointCollectionName}/${docKey}`); - /* Use set to write the data to this reference */ await set(dataRef, data); return { @@ -273,7 +254,6 @@ export class FirebaseSaver extends BaseCheckpointSaver { }; } - /* Saves intermediate writes associated with a checkpoint to the Firestore database. */ async putWrites( config: RunnableConfig, writes: PendingWrite[], @@ -302,8 +282,7 @@ export class FirebaseSaver extends BaseCheckpointSaver { const [channel, value] = write; const [type, serializedValue] = this.serde.dumpsTyped(value); - /* "thread_id", "checkpoint_ns", "checkpoint_id", "taskId" and "idx" - form the "primary key" for each checkpoint write */ + const writeKey = `${thread_id}_${checkpoint_ns}_${checkpoint_id}_${taskId}_${idx}`; currentData[writeKey] = { diff --git a/libs/checkpoint-firebase/src/tests/checkpoints.int.test.ts b/libs/checkpoint-firebase/src/tests/checkpoints.int.test.ts index d68b4977..22c8726e 100644 --- a/libs/checkpoint-firebase/src/tests/checkpoints.int.test.ts +++ b/libs/checkpoint-firebase/src/tests/checkpoints.int.test.ts @@ -1,86 +1,8 @@ -import { describe, it, expect, beforeAll, afterAll } from "@jest/globals"; +import { describe, it, expect, afterAll } from "@jest/globals"; import { Checkpoint, CheckpointTuple, uuid6 } from "@langchain/langgraph-checkpoint"; import { FirebaseSaver } from "../index.js"; import { initializeApp } from "firebase/app"; import { getDatabase, ref, remove, Database } from "firebase/database"; -import { GenericContainer, StartedTestContainer } from "testcontainers"; - -const FIREBASE_PORT = 9000; - -// Example: Replace this URL with your database URL -const databaseURL = "https://your-database-name.firebaseio.com"; - -// Initialize Firebase App with only the databaseURL -const app = initializeApp({ - databaseURL: databaseURL, -}); - -// Get the database instance -const database = getDatabase(app); - -console.log("Database initialized with URL:", databaseURL); - -// class FirebaseTestContainer { -// container?: StartedTestContainer; - -// async start() { -// this.container = await new GenericContainer("firebase/firebase-tools") -// .withExposedPorts(FIREBASE_PORT) -// .withCmd([ -// "emulators:start", -// "--only", -// "database", -// "--project", -// "test-project", -// ]) -// .start(); - -// return this.getDatabaseUrl(); -// } - -// async stop() { -// if (this.container) { -// await this.container.stop(); -// } -// } - -// getDatabaseUrl() { -// if (!this.container) { -// throw new Error("Firebase container has not been started."); -// } - -// const port = this.container.getMappedPort(FIREBASE_PORT); -// return `http://localhost:${port}`; -// } -// } - -// const testContainer = new FirebaseTestContainer(); - -// export const initializer: any = { -// checkpointerName: "@langchain/langgraph-checkpoint-firebase", - -// async beforeAll() { -// const databaseUrl = await testContainer.start(); - -// // Initialize Firebase Client SDK pointing to the emulator -// initializeApp({ -// databaseURL: databaseUrl, -// }); - -// console.log(`Firebase Emulator running at ${databaseUrl}`); -// }, - -// beforeAllTimeout: 300_000, // five minutes to set up Firebase emulator - -// async createCheckpointer() { -// const database = getDatabase(); -// return new FirebaseSaver(database); -// }, - -// async afterAll() { -// await testContainer.stop(); -// }, -// }; // Define test checkpoints const checkpoint1: Checkpoint = { @@ -109,19 +31,16 @@ async function clearCollection(database: Database, path: string): Promise await remove(collectionRef); } -let saver: FirebaseSaver; -let database: Database; +const app = initializeApp({ + databaseURL: process.env.FIREBASE_URL +}); -beforeAll(async () => { - await initializer.beforeAll(); - saver = await initializer.createCheckpointer(); - database = getDatabase(); // Access database for cleanup -}, initializer.beforeAllTimeout); +const database = getDatabase(app); +let saver = new FirebaseSaver(database); afterAll(async () => { await clearCollection(database, "checkpoints"); await clearCollection(database, "checkpoint-writes"); - await initializer.afterAll(); }); describe("FirebaseSaver", () => { diff --git a/libs/checkpoint-validation/package.json b/libs/checkpoint-validation/package.json index fc71781c..d4479e07 100644 --- a/libs/checkpoint-validation/package.json +++ b/libs/checkpoint-validation/package.json @@ -75,7 +75,7 @@ "prettier": "^2.8.3", "release-it": "^17.6.0", "rollup": "^4.22.4", - "typescript": "^4.9.5 || ^5.4.5" + "typescript": "^5.7.2" }, "publishConfig": { "access": "public", diff --git a/libs/checkpoint-validation/src/tests/firebase_initializer.ts b/libs/checkpoint-validation/src/tests/firebase_initializer.ts index a348211f..97815f7c 100644 --- a/libs/checkpoint-validation/src/tests/firebase_initializer.ts +++ b/libs/checkpoint-validation/src/tests/firebase_initializer.ts @@ -1,78 +1,41 @@ import { FirebaseSaver } from "@langchain/langgraph-checkpoint-firebase"; -import { initializeApp} from "firebase/app"; +import { initializeApp } from "firebase/app"; +import { getDatabase, Database } from "firebase/database"; import type { CheckpointerTestInitializer } from "../types.js"; -import { GenericContainer, StartedTestContainer } from "testcontainers"; -import { getDatabase} from "firebase/database"; - -const FIREBASE_PORT = 9000; - -class FirebaseTestContainer { - container?: StartedTestContainer; - - async start() { - this.container = await new GenericContainer("firebase/firebase-tools") - .withExposedPorts(FIREBASE_PORT) - .withCmd([ - "emulators:start", - "--only", - "database", - "--project", - "test-project", - ]) - .start(); - - return this.getDatabaseUrl(); - } - - async stop() { - if (this.container) { - await this.container.stop(); - } - } - - getDatabaseUrl() { - if (!this.container) { - throw new Error("Firebase container has not been started."); - } - - const port = this.container.getMappedPort(FIREBASE_PORT); - return `http://localhost:${port}`; - } -} - - - -const testContainer = new FirebaseTestContainer(); +let database: Database; export const initializer: CheckpointerTestInitializer = { checkpointerName: "@langchain/langgraph-checkpoint-firebase", async beforeAll() { - const databaseUrl = await testContainer.start(); - databaseUrl.getMappedPort() - - - // Initialize Firebase SDK pointing to the emulator - initializeApp({ - apiKey: "fake-api-key", // Firebase requires a fake API key for emulator use + // Ensure the Firebase Emulator is running locally + const firebaseConfig = { + apiKey: "test-api-key", authDomain: "localhost", - projectId: "test-project", // Match the emulator's projectId - databaseURL: , - }); + projectId: "test-project", + databaseURL: process.env.FIREBASEURL || "http://localhost:9000", // Use emulator URL + }; + process.env.FIREBASE_URL = process.env.FIREBASEURL || "http://localhost:9000" + // Initialize Firebase app + const app = initializeApp(firebaseConfig); + + // Initialize Firebase Realtime Database + database = getDatabase(app); - console.log(`Firebase Emulator running at ${databaseUrl}`); + console.log("Connected to Firebase Realtime Database Emulator"); }, - beforeAllTimeout: 300_000, // five minutes to set up Firebase emulator + beforeAllTimeout: 300_000, // Allow up to 5 minutes for emulator setup async createCheckpointer() { - const database = getDatabase(); + // Create a new instance of FirebaseSaver with the initialized database return new FirebaseSaver(database); }, async afterAll() { - await testContainer.stop(); + console.log("Cleaning up Firebase Realtime Database Emulator"); + // Optionally, you can implement cleanup logic here if necessary }, };