mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-08 07:17:39 +00:00
refactor(sync): replace message reloads with incremental tail sync
This commit is contained in:
@@ -24,6 +24,7 @@ describe('cancelQueuedMessage', () => {
|
||||
// Row should be gone from uninvoked list
|
||||
const remaining = store.messages.getUninvokedLocalMessages(session.id)
|
||||
expect(remaining).toHaveLength(0)
|
||||
expect(store.messages.getMessageEpoch(session.id)).toBe(1)
|
||||
})
|
||||
|
||||
it('already-invoked: returns status=invoked with full message row, row stays in DB', () => {
|
||||
@@ -67,6 +68,7 @@ describe('cancelQueuedMessage', () => {
|
||||
if (second.status === 'cancelled') {
|
||||
expect(second.localId).toBeNull()
|
||||
}
|
||||
expect(store.messages.getMessageEpoch(session.id)).toBe(1)
|
||||
})
|
||||
|
||||
it('non-existent messageId: returns status=cancelled with localId=null', () => {
|
||||
@@ -173,6 +175,75 @@ describe('cancelQueuedMessage', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('position pagination and structural epochs', () => {
|
||||
it('returns rows strictly after a cursor and respects an inclusive snapshot head', () => {
|
||||
const store = makeStore()
|
||||
const session = makeSession(store, 'position-after')
|
||||
const first = store.messages.addMessage(session.id, { text: 'first' })
|
||||
const second = store.messages.addMessage(session.id, { text: 'second' })
|
||||
const third = store.messages.addMessage(session.id, { text: 'third' })
|
||||
store.messages.addMessage(session.id, { text: 'fourth' })
|
||||
|
||||
const rows = store.messages.getMessagesAfterPosition(
|
||||
session.id,
|
||||
10,
|
||||
{ at: first.invokedAt ?? first.createdAt, seq: first.seq },
|
||||
{ at: third.invokedAt ?? third.createdAt, seq: third.seq }
|
||||
)
|
||||
|
||||
expect(rows.map((message) => message.id)).toEqual([second.id, third.id])
|
||||
})
|
||||
|
||||
it('reports the newest composite position', () => {
|
||||
const store = makeStore()
|
||||
const session = makeSession(store, 'position-head')
|
||||
const first = store.messages.addMessage(session.id, { text: 'first' })
|
||||
const second = store.messages.addMessage(session.id, { text: 'second' })
|
||||
|
||||
expect(store.messages.getNewestMessagePosition(session.id)).toEqual({
|
||||
at: second.invokedAt ?? second.createdAt,
|
||||
seq: second.seq
|
||||
})
|
||||
expect(first.seq).toBeLessThan(second.seq)
|
||||
})
|
||||
|
||||
it('bumps both epochs when session history is merged', () => {
|
||||
const store = makeStore()
|
||||
const source = makeSession(store, 'epoch-merge-source')
|
||||
const target = makeSession(store, 'epoch-merge-target')
|
||||
store.messages.addMessage(source.id, { text: 'source' })
|
||||
store.messages.addMessage(target.id, { text: 'target' })
|
||||
|
||||
const result = store.messages.mergeSessionMessages(source.id, target.id)
|
||||
|
||||
expect(result.moved).toBe(1)
|
||||
expect(store.messages.getMessageEpoch(source.id)).toBe(1)
|
||||
expect(store.messages.getMessageEpoch(target.id)).toBe(1)
|
||||
})
|
||||
|
||||
it('bumps the target epoch when a copied message lands behind the cached head', () => {
|
||||
const store = makeStore()
|
||||
const target = makeSession(store, 'epoch-copy-target')
|
||||
const head = store.messages.addMessage(target.id, { text: 'head' })
|
||||
const headPosition = {
|
||||
at: head.invokedAt ?? head.createdAt,
|
||||
seq: head.seq
|
||||
}
|
||||
|
||||
const copied = store.messages.copyMessageToSession(target.id, {
|
||||
content: { text: 'historical' },
|
||||
createdAt: headPosition.at - 1_000,
|
||||
localId: null,
|
||||
invokedAt: headPosition.at - 1_000,
|
||||
scheduledAt: null
|
||||
})
|
||||
|
||||
expect(copied.seq).toBeGreaterThan(head.seq)
|
||||
expect(store.messages.getMessagesAfterPosition(target.id, 10, headPosition)).toEqual([])
|
||||
expect(store.messages.getMessageEpoch(target.id)).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('addMessage: scheduledAt invariants', () => {
|
||||
it('rejects scheduledAt without a localId — would silently invoke immediately', () => {
|
||||
const store = makeStore()
|
||||
|
||||
Reference in New Issue
Block a user