@@ -18,159 +18,166 @@ import {
1818 uuid6 ,
1919} from "@langchain/langgraph-checkpoint" ;
2020import { Migration1ObjectMetadata } from "../../migrations/1_object_metadata.js" ;
21+ import { isSkippedCIEnvironment } from "../utils.js" ;
2122
2223describe ( "1_object_metadata" , ( ) => {
23- const dbName = "test_db" ;
24- let container : StartedMongoDBContainer ;
25- let client : MongoClient ;
26-
27- beforeAll ( async ( ) => {
28- container = await new MongoDBContainer ( "mongo:6.0.1" ) . start ( ) ;
29- const connectionString = `mongodb://127.0.0.1:${ container . getMappedPort (
30- 27017
31- ) } /${ dbName } ?directConnection=true`;
32- client = new MongoClient ( connectionString ) ;
33- } ) ;
34-
35- afterAll ( async ( ) => {
36- await client . close ( ) ;
37- await container . stop ( ) ;
38- } ) ;
39-
40- describe ( "isApplicable" , ( ) => {
41- // MongoDBSaver handles this automatically in initializeSchemaVersion
42- it ( "should want to apply on empty database" , async ( ) => {
43- // ensure database is empty
44- const db = client . db ( dbName ) ;
45- await db . dropDatabase ( ) ;
46-
47- const migration = new Migration1ObjectMetadata ( {
48- client,
49- dbName,
50- checkpointCollectionName : "checkpoints" ,
51- checkpointWritesCollectionName : "checkpoint_writes" ,
52- schemaVersionCollectionName : "schema_version" ,
53- serializer : new JsonPlusSerializer ( ) ,
54- currentSchemaVersion : 1 ,
55- } ) ;
56- expect ( await migration . isApplicable ( ) ) . toBe ( true ) ;
24+ if ( ! isSkippedCIEnvironment ( ) ) {
25+ const dbName = "test_db" ;
26+ let container : StartedMongoDBContainer ;
27+ let client : MongoClient ;
28+
29+ beforeAll ( async ( ) => {
30+ container = await new MongoDBContainer ( "mongo:6.0.1" ) . start ( ) ;
31+ const connectionString = `mongodb://127.0.0.1:${ container . getMappedPort (
32+ 27017
33+ ) } /${ dbName } ?directConnection=true`;
34+ client = new MongoClient ( connectionString ) ;
5735 } ) ;
5836
59- it ( "should not want to apply on database with schema version of 1" , async ( ) => {
60- const db = client . db ( dbName ) ;
61- await db . dropDatabase ( ) ;
62- await db . createCollection ( "schema_version" ) ;
63- await db . collection ( "schema_version" ) . insertOne ( { version : 1 } ) ;
64-
65- const migration = new Migration1ObjectMetadata ( {
66- client,
67- dbName,
68- checkpointCollectionName : "checkpoints" ,
69- checkpointWritesCollectionName : "checkpoint_writes" ,
70- schemaVersionCollectionName : "schema_version" ,
71- serializer : new JsonPlusSerializer ( ) ,
72- currentSchemaVersion : 1 ,
73- } ) ;
74- expect ( await migration . isApplicable ( ) ) . toBe ( false ) ;
37+ afterAll ( async ( ) => {
38+ await client . close ( ) ;
39+ await container . stop ( ) ;
7540 } ) ;
76- } ) ;
77-
78- describe ( "apply" , ( ) => {
79- const expectedCheckpoints : Record <
80- string ,
81- {
82- parent_checkpoint_id ?: string ;
83- checkpoint : Binary ;
84- type : string ;
85- metadata : CheckpointMetadata ;
86- thread_id : string ;
87- checkpoint_ns : string ;
88- checkpoint_id : string ;
89- }
90- > = { } ;
91-
92- beforeEach ( async ( ) => {
93- const serde = new JsonPlusSerializer ( ) ;
94- const dropDb = client . db ( dbName ) ;
95- await dropDb . dropDatabase ( ) ;
96- const db = client . db ( dbName ) ;
97- await db . createCollection ( "checkpoints" ) ;
98- await db . createCollection ( "schema_version" ) ;
99-
100- for ( let i = 0 ; i < 10 ; i += 1 ) {
101- const checkpoint_id = uuid6 ( - 3 ) ;
102- const thread_id = uuid6 ( - 3 ) ;
103- const checkpoint_ns = "" ;
104-
105- const checkpoint : Checkpoint = {
106- v : 1 ,
107- id : checkpoint_id ,
108- ts : new Date ( ) . toISOString ( ) ,
109- channel_values : { } ,
110- channel_versions : { } ,
111- versions_seen : { } ,
112- pending_sends : [ ] ,
113- } ;
114-
115- const metadata : CheckpointMetadata = {
116- source : "update" ,
117- step : - 1 ,
118- writes : { } ,
119- parents : { } ,
120- } ;
121-
122- const [ checkpointType , serializedCheckpoint ] =
123- serde . dumpsTyped ( checkpoint ) ;
124- const serializedMetadata = serde . dumpsTyped ( metadata ) [ 1 ] ;
125-
126- await db . collection ( "checkpoints" ) . insertOne ( {
127- type : checkpointType ,
128- checkpoint : serializedCheckpoint ,
129- metadata : serializedMetadata ,
130- thread_id,
131- checkpoint_ns,
132- checkpoint_id,
41+
42+ describe ( "isApplicable" , ( ) => {
43+ // MongoDBSaver handles this automatically in initializeSchemaVersion
44+ it ( "should want to apply on empty database" , async ( ) => {
45+ // ensure database is empty
46+ const db = client . db ( dbName ) ;
47+ await db . dropDatabase ( ) ;
48+
49+ const migration = new Migration1ObjectMetadata ( {
50+ client,
51+ dbName,
52+ checkpointCollectionName : "checkpoints" ,
53+ checkpointWritesCollectionName : "checkpoint_writes" ,
54+ schemaVersionCollectionName : "schema_version" ,
55+ serializer : new JsonPlusSerializer ( ) ,
56+ currentSchemaVersion : 1 ,
13357 } ) ;
58+ expect ( await migration . isApplicable ( ) ) . toBe ( true ) ;
59+ } ) ;
13460
135- expectedCheckpoints [ checkpoint_id ] = {
136- checkpoint : new Binary ( serializedCheckpoint ) ,
137- type : checkpointType ,
138- metadata,
139- thread_id,
140- checkpoint_ns,
141- checkpoint_id,
142- } ;
143- }
61+ it ( "should not want to apply on database with schema version of 1" , async ( ) => {
62+ const db = client . db ( dbName ) ;
63+ await db . dropDatabase ( ) ;
64+ await db . createCollection ( "schema_version" ) ;
65+ await db . collection ( "schema_version" ) . insertOne ( { version : 1 } ) ;
66+
67+ const migration = new Migration1ObjectMetadata ( {
68+ client,
69+ dbName,
70+ checkpointCollectionName : "checkpoints" ,
71+ checkpointWritesCollectionName : "checkpoint_writes" ,
72+ schemaVersionCollectionName : "schema_version" ,
73+ serializer : new JsonPlusSerializer ( ) ,
74+ currentSchemaVersion : 1 ,
75+ } ) ;
76+ expect ( await migration . isApplicable ( ) ) . toBe ( false ) ;
77+ } ) ;
14478 } ) ;
14579
146- it ( "should migrate all checkpoints" , async ( ) => {
147- const migration = new Migration1ObjectMetadata ( {
148- client,
149- dbName,
150- checkpointCollectionName : "checkpoints" ,
151- checkpointWritesCollectionName : "checkpoint_writes" ,
152- schemaVersionCollectionName : "schema_version" ,
153- serializer : new JsonPlusSerializer ( ) ,
154- currentSchemaVersion : 1 ,
80+ describe ( "apply" , ( ) => {
81+ const expectedCheckpoints : Record <
82+ string ,
83+ {
84+ parent_checkpoint_id ?: string ;
85+ checkpoint : Binary ;
86+ type : string ;
87+ metadata : CheckpointMetadata ;
88+ thread_id : string ;
89+ checkpoint_ns : string ;
90+ checkpoint_id : string ;
91+ }
92+ > = { } ;
93+
94+ beforeEach ( async ( ) => {
95+ const serde = new JsonPlusSerializer ( ) ;
96+ const dropDb = client . db ( dbName ) ;
97+ await dropDb . dropDatabase ( ) ;
98+ const db = client . db ( dbName ) ;
99+ await db . createCollection ( "checkpoints" ) ;
100+ await db . createCollection ( "schema_version" ) ;
101+
102+ for ( let i = 0 ; i < 10 ; i += 1 ) {
103+ const checkpoint_id = uuid6 ( - 3 ) ;
104+ const thread_id = uuid6 ( - 3 ) ;
105+ const checkpoint_ns = "" ;
106+
107+ const checkpoint : Checkpoint = {
108+ v : 1 ,
109+ id : checkpoint_id ,
110+ ts : new Date ( ) . toISOString ( ) ,
111+ channel_values : { } ,
112+ channel_versions : { } ,
113+ versions_seen : { } ,
114+ pending_sends : [ ] ,
115+ } ;
116+
117+ const metadata : CheckpointMetadata = {
118+ source : "update" ,
119+ step : - 1 ,
120+ writes : { } ,
121+ parents : { } ,
122+ } ;
123+
124+ const [ checkpointType , serializedCheckpoint ] =
125+ serde . dumpsTyped ( checkpoint ) ;
126+ const serializedMetadata = serde . dumpsTyped ( metadata ) [ 1 ] ;
127+
128+ await db . collection ( "checkpoints" ) . insertOne ( {
129+ type : checkpointType ,
130+ checkpoint : serializedCheckpoint ,
131+ metadata : serializedMetadata ,
132+ thread_id,
133+ checkpoint_ns,
134+ checkpoint_id,
135+ } ) ;
136+
137+ expectedCheckpoints [ checkpoint_id ] = {
138+ checkpoint : new Binary ( serializedCheckpoint ) ,
139+ type : checkpointType ,
140+ metadata,
141+ thread_id,
142+ checkpoint_ns,
143+ checkpoint_id,
144+ } ;
145+ }
146+ } ) ;
147+
148+ it ( "should migrate all checkpoints" , async ( ) => {
149+ const migration = new Migration1ObjectMetadata ( {
150+ client,
151+ dbName,
152+ checkpointCollectionName : "checkpoints" ,
153+ checkpointWritesCollectionName : "checkpoint_writes" ,
154+ schemaVersionCollectionName : "schema_version" ,
155+ serializer : new JsonPlusSerializer ( ) ,
156+ currentSchemaVersion : 1 ,
157+ } ) ;
158+ await migration . apply ( ) ;
159+
160+ const db = client . db ( dbName ) ;
161+ const cursor = await db . collection ( "checkpoints" ) . find ( { } ) ;
162+
163+ let docCount = 0 ;
164+ for await ( const actual of cursor ) {
165+ docCount += 1 ;
166+ const expected = expectedCheckpoints [ actual . checkpoint_id ] ;
167+ expect ( actual . parent_checkpoint_id ) . toBe (
168+ expected . parent_checkpoint_id
169+ ) ;
170+ expect ( actual . type ) . toBe ( expected . type ) ;
171+ expect ( actual . checkpoint ) . toEqual ( expected . checkpoint ) ;
172+ expect ( actual . metadata ) . toEqual ( expected . metadata ) ;
173+ expect ( actual . thread_id ) . toBe ( expected . thread_id ) ;
174+ expect ( actual . checkpoint_ns ) . toBe ( expected . checkpoint_ns ) ;
175+ expect ( actual . checkpoint_id ) . toBe ( expected . checkpoint_id ) ;
176+ }
177+ expect ( docCount ) . toBe ( 10 ) ;
155178 } ) ;
156- await migration . apply ( ) ;
157-
158- const db = client . db ( dbName ) ;
159- const cursor = await db . collection ( "checkpoints" ) . find ( { } ) ;
160-
161- let docCount = 0 ;
162- for await ( const actual of cursor ) {
163- docCount += 1 ;
164- const expected = expectedCheckpoints [ actual . checkpoint_id ] ;
165- expect ( actual . parent_checkpoint_id ) . toBe ( expected . parent_checkpoint_id ) ;
166- expect ( actual . type ) . toBe ( expected . type ) ;
167- expect ( actual . checkpoint ) . toEqual ( expected . checkpoint ) ;
168- expect ( actual . metadata ) . toEqual ( expected . metadata ) ;
169- expect ( actual . thread_id ) . toBe ( expected . thread_id ) ;
170- expect ( actual . checkpoint_ns ) . toBe ( expected . checkpoint_ns ) ;
171- expect ( actual . checkpoint_id ) . toBe ( expected . checkpoint_id ) ;
172- }
173- expect ( docCount ) . toBe ( 10 ) ;
174179 } ) ;
175- } ) ;
180+ } else {
181+ it . skip ( "GitHub can't run containers on M-Series macOS runners due to lack of support for nested virtualization." , ( ) => { } ) ;
182+ }
176183} ) ;
0 commit comments