Skip to content

Commit 8e1a654

Browse files
committed
feat(files): improve editor recovery and editing controls
1 parent 7cfd00a commit 8e1a654

46 files changed

Lines changed: 5352 additions & 481 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/realtime/src/handlers/file-doc-store.test.ts

Lines changed: 550 additions & 17 deletions
Large diffs are not rendered by default.

apps/realtime/src/handlers/file-doc-store.ts

Lines changed: 452 additions & 72 deletions
Large diffs are not rendered by default.

apps/realtime/src/handlers/file-doc.join-readiness.test.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,19 @@ vi.mock('redis', () => {
6363
for (let i = 0; i < backing.readDelayTicks; i++) await Promise.resolve()
6464
return (backing.streams.get(key) ?? []).map((e) => ({ ...e }))
6565
},
66+
xRevRange: async (key: string) =>
67+
[...(backing.streams.get(key) ?? [])]
68+
.reverse()
69+
.slice(0, 1)
70+
.map((entry) => ({ ...entry })),
6671
xLen: async (key: string) => (backing.streams.get(key) ?? []).length,
67-
xRead: async (streams: { key: string; id: string }[]) => {
72+
xRead: async (streams: { key: string; id: string }[], options?: { COUNT?: number }) => {
6873
const res: { name: string; messages: { id: string; message: Record<string, string> }[] }[] =
6974
[]
7075
for (const { key, id } of streams) {
71-
const after = (backing.streams.get(key) ?? []).filter((e) => seqOf(e.id) > seqOf(id))
76+
const after = (backing.streams.get(key) ?? [])
77+
.filter((e) => seqOf(e.id) > seqOf(id))
78+
.slice(0, options?.COUNT)
7279
if (after.length) res.push({ name: key, messages: after.map((e) => ({ ...e })) })
7380
}
7481
if (res.length) return res

apps/realtime/src/handlers/file-doc.multireplica.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const fakeStore = {
2525
versions: new Map<string, number>(),
2626
acquireMergeSlot: vi.fn(async () => 'token'),
2727
releaseMergeSlot: vi.fn(async () => {}),
28+
getDocumentGeneration: vi.fn(async () => 'shared-generation'),
2829
getStreamState: vi.fn(async () => new Uint8Array([1])),
2930
publishAndWait: vi.fn(async () => {}),
3031
getSyncedVersion: vi.fn(async (name: string) => fakeStore.versions.get(name) ?? null),
@@ -67,7 +68,13 @@ describe('applyMarkdownToLiveFileDoc — multi-replica (store-enabled) ordering'
6768
expect(await applyMarkdownToLiveFileDoc('file-1', '# durable', { version: 100 })).toBe(
6869
'applied'
6970
)
70-
expect(fakeStore.setSyncedVersion).toHaveBeenCalledWith(ROOM_NAME, 100)
71+
expect(fakeStore.setSyncedVersion).toHaveBeenCalledWith(ROOM_NAME, 100, 'shared-generation')
72+
expect(fakeStore.getStreamState).toHaveBeenCalledWith(ROOM_NAME, 'shared-generation')
73+
expect(fakeStore.publishAndWait).toHaveBeenCalledWith(
74+
ROOM_NAME,
75+
expect.any(Uint8Array),
76+
'shared-generation'
77+
)
7178
mockFetchFileDocMerge.mockClear()
7279

7380
// A durable write with an OLDER version than the SHARED synced version is stale — rejected under the
@@ -81,7 +88,7 @@ describe('applyMarkdownToLiveFileDoc — multi-replica (store-enabled) ordering'
8188
expect(await applyMarkdownToLiveFileDoc('file-1', '# durable again', { version: 150 })).toBe(
8289
'applied'
8390
)
84-
expect(fakeStore.setSyncedVersion).toHaveBeenCalledWith(ROOM_NAME, 150)
91+
expect(fakeStore.setSyncedVersion).toHaveBeenCalledWith(ROOM_NAME, 150, 'shared-generation')
8592
// setSyncedVersion fired only for the two applied durable writes, never for the stale one.
8693
expect(fakeStore.setSyncedVersion).toHaveBeenCalledTimes(2)
8794
})
@@ -98,7 +105,7 @@ describe('applyMarkdownToLiveFileDoc — multi-replica (store-enabled) ordering'
98105
).toBe('applied')
99106
expect(mockFetchFileDocMerge).not.toHaveBeenCalled() // content deferred to the client
100107
expect(fakeStore.publishAndWait).not.toHaveBeenCalled()
101-
expect(fakeStore.setSyncedVersion).toHaveBeenCalledWith(ROOM_NAME, 100) // version still recorded
108+
expect(fakeStore.setSyncedVersion).toHaveBeenCalledWith(ROOM_NAME, 100, 'shared-generation') // version still recorded
102109

103110
// Once streaming stops the flag clears and the (now near-noop) durable merge resumes normally.
104111
fakeStore.isAgentStreaming.mockResolvedValue(false)

0 commit comments

Comments
 (0)