@mastra/clickhouse 0.11.1-alpha.0 → 0.11.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +26 -0
- package/dist/_tsup-dts-rollup.d.cts +8 -4
- package/dist/_tsup-dts-rollup.d.ts +8 -4
- package/dist/index.cjs +348 -100
- package/dist/index.js +330 -82
- package/package.json +3 -3
- package/src/storage/index.test.ts +78 -0
- package/src/storage/index.ts +362 -99
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
createSampleThread,
|
|
5
5
|
createSampleWorkflowSnapshot,
|
|
6
6
|
checkWorkflowSnapshot,
|
|
7
|
+
createSampleMessageV2,
|
|
7
8
|
} from '@internal/storage-test-utils';
|
|
8
9
|
import type { MastraMessageV1, StorageColumn, WorkflowRunState } from '@mastra/core';
|
|
9
10
|
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
@@ -236,6 +237,83 @@ describe('ClickhouseStore', () => {
|
|
|
236
237
|
});
|
|
237
238
|
}, 10e3);
|
|
238
239
|
|
|
240
|
+
it('should upsert messages: duplicate id+threadId results in update, not duplicate row', async () => {
|
|
241
|
+
const thread = await createSampleThread({ resourceId: 'clickhouse-test' });
|
|
242
|
+
await store.saveThread({ thread });
|
|
243
|
+
const baseMessage = createSampleMessageV2({
|
|
244
|
+
threadId: thread.id,
|
|
245
|
+
createdAt: new Date(),
|
|
246
|
+
content: { content: 'Original' },
|
|
247
|
+
resourceId: 'clickhouse-test',
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Insert the message for the first time
|
|
251
|
+
await store.saveMessages({ messages: [baseMessage], format: 'v2' });
|
|
252
|
+
|
|
253
|
+
// Insert again with the same id and threadId but different content
|
|
254
|
+
const updatedMessage = {
|
|
255
|
+
...createSampleMessageV2({
|
|
256
|
+
threadId: thread.id,
|
|
257
|
+
createdAt: new Date(),
|
|
258
|
+
content: { content: 'Updated' },
|
|
259
|
+
resourceId: 'clickhouse-test',
|
|
260
|
+
}),
|
|
261
|
+
id: baseMessage.id,
|
|
262
|
+
};
|
|
263
|
+
await store.saveMessages({ messages: [updatedMessage], format: 'v2' });
|
|
264
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
265
|
+
|
|
266
|
+
// Retrieve messages for the thread
|
|
267
|
+
const retrievedMessages = await store.getMessages({ threadId: thread.id, format: 'v2' });
|
|
268
|
+
|
|
269
|
+
// Only one message should exist for that id+threadId
|
|
270
|
+
expect(retrievedMessages.filter(m => m.id === baseMessage.id)).toHaveLength(1);
|
|
271
|
+
|
|
272
|
+
// The content should be the updated one
|
|
273
|
+
expect(retrievedMessages.find(m => m.id === baseMessage.id)?.content.content).toBe('Updated');
|
|
274
|
+
}, 10e3);
|
|
275
|
+
|
|
276
|
+
it('should upsert messages: duplicate id and different threadid', async () => {
|
|
277
|
+
const thread1 = await createSampleThread();
|
|
278
|
+
const thread2 = await createSampleThread();
|
|
279
|
+
await store.saveThread({ thread: thread1 });
|
|
280
|
+
await store.saveThread({ thread: thread2 });
|
|
281
|
+
|
|
282
|
+
const message = createSampleMessageV2({
|
|
283
|
+
threadId: thread1.id,
|
|
284
|
+
createdAt: new Date(),
|
|
285
|
+
content: { content: 'Thread1 Content' },
|
|
286
|
+
resourceId: thread1.resourceId,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Insert message into thread1
|
|
290
|
+
await store.saveMessages({ messages: [message], format: 'v2' });
|
|
291
|
+
|
|
292
|
+
// Attempt to insert a message with the same id but different threadId
|
|
293
|
+
const conflictingMessage = {
|
|
294
|
+
...createSampleMessageV2({
|
|
295
|
+
threadId: thread2.id,
|
|
296
|
+
createdAt: new Date(),
|
|
297
|
+
content: { content: 'Thread2 Content' },
|
|
298
|
+
resourceId: thread2.resourceId,
|
|
299
|
+
}),
|
|
300
|
+
id: message.id,
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// Save should also save the message to the new thread
|
|
304
|
+
await store.saveMessages({ messages: [conflictingMessage], format: 'v2' });
|
|
305
|
+
|
|
306
|
+
// Retrieve messages for both threads
|
|
307
|
+
const thread1Messages = await store.getMessages({ threadId: thread1.id, format: 'v2' });
|
|
308
|
+
const thread2Messages = await store.getMessages({ threadId: thread2.id, format: 'v2' });
|
|
309
|
+
|
|
310
|
+
// Thread 1 should have the message with that id
|
|
311
|
+
expect(thread1Messages.find(m => m.id === message.id)?.content.content).toBe('Thread1 Content');
|
|
312
|
+
|
|
313
|
+
// Thread 2 should have the message with that id
|
|
314
|
+
expect(thread2Messages.find(m => m.id === message.id)?.content.content).toBe('Thread2 Content');
|
|
315
|
+
}, 10e3);
|
|
316
|
+
|
|
239
317
|
// it('should retrieve messages w/ next/prev messages by message id + resource id', async () => {
|
|
240
318
|
// const messages: MastraMessageV2[] = [
|
|
241
319
|
// createSampleMessageV2({ threadId: 'thread-one', content: 'First', resourceId: 'cross-thread-resource' }),
|