Skip to content

Commit

Permalink
Keep local sync maps in the log
Browse files Browse the repository at this point in the history
  • Loading branch information
ai committed Sep 23, 2023
1 parent 886084d commit 9d363e0
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 49 deletions.
8 changes: 6 additions & 2 deletions create-filter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,12 @@ export function createFilter(client, Template, filter = {}, opts = {}) {
endTask()
resolve()
} else if (Template.remote) {
let subscribeSinceLatest = latestMeta !== undefined
? { ...subscribe, since: { id: latestMeta.id, time: latestMeta.time } }
let subscribeSinceLatest =
latestMeta !== undefined
? {
...subscribe,
since: { id: latestMeta.id, time: latestMeta.time }
}
: subscribe
await processSubscribe(client.sync(subscribeSinceLatest))
}
Expand Down
18 changes: 9 additions & 9 deletions react/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,13 @@ it('recreating filter on args changes', async () => {

await act(async () => {
await Promise.all([
createSyncMap(client, LocalPost, { id: '1', projectId: '1', title: 'Y' }),
createSyncMap(client, LocalPost, { id: '2', projectId: '2', title: 'Y' }),
createSyncMap(client, LocalPost, { id: '3', projectId: '1', title: 'A' })
createSyncMap(client, LocalPost, { id: '1', projectId: '1', title: '1' }),
createSyncMap(client, LocalPost, { id: '2', projectId: '5', title: '2' }),
createSyncMap(client, LocalPost, { id: '3', projectId: '1', title: '3' })
])
await delay(10)
})
expect(screen.getByTestId('test').textContent).toBe(' 0:Y 1:A')
expect(screen.getByTestId('test').textContent).toBe(' 0:1 1:3')
expect(renders).toEqual(['list', 'list', '1', '3'])

renders.splice(0, renders.length)
Expand All @@ -473,15 +473,15 @@ it('recreating filter on args changes', async () => {
renders.splice(0, renders.length)
await act(async () => {
await Promise.all([
createSyncMap(client, LocalPost, { id: '1', projectId: '1', title: 'Y' }),
createSyncMap(client, LocalPost, { id: '2', projectId: '2', title: 'Y' }),
createSyncMap(client, LocalPost, { id: '3', projectId: '1', title: 'A' })
createSyncMap(client, LocalPost, { id: '4', projectId: '1', title: '4' }),
createSyncMap(client, LocalPost, { id: '5', projectId: '2', title: '5' }),
createSyncMap(client, LocalPost, { id: '6', projectId: '1', title: '6' })
])
await delay(10)
})
await delay(10)
expect(screen.getByTestId('test').textContent).toBe(' 0:Y')
expect(renders).toEqual(['list', '2'])
expect(screen.getByTestId('test').textContent).toBe(' 0:5')
expect(renders).toEqual(['list', '5'])
})

it('renders authentication state', async () => {
Expand Down
94 changes: 72 additions & 22 deletions sync-map-template/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,8 @@ export function syncMapTemplate(plural, opts = {}) {
return Template
}

function addSyncAction(client, Template, action) {
let meta = { indexes: getIndexes(Template.plural, action.id) }
if (!Template.remote) {
action.type += 'd'
}
function addSyncAction(client, Template, action, meta = {}) {
meta.indexes = getIndexes(Template.plural, action.id)
if (Template.remote) {
return task(() => client.sync(action, meta))
} else {
Expand All @@ -354,11 +351,26 @@ function addSyncAction(client, Template, action) {

export function createSyncMap(client, Template, value) {
let { id, ...fields } = value
return addSyncAction(client, Template, {
fields,
id,
type: `${Template.plural}/create`
})
if (Template.remote) {
return addSyncAction(client, Template, {
fields,
id,
type: `${Template.plural}/create`
})
} else {
return addSyncAction(
client,
Template,
{
fields,
id,
type: `${Template.plural}/created`
},
{
reasons: Object.keys(fields).map(i => `${Template.plural}/${id}/${i}`)
}
)
}
}

export async function buildNewSyncMap(client, Template, value) {
Expand All @@ -373,20 +385,44 @@ export async function buildNewSyncMap(client, Template, value) {
indexes: getIndexes(Template.plural, id),
time: parseInt(actionId)
}
if (Template.remote) meta.sync = true
if (Template.remote) {
meta.sync = true
} else {
meta.reasons = Object.keys(fields).map(i => `${Template.plural}/${id}/${i}`)
}
await task(() => client.log.add(action, meta))

let store = Template(id, client, action, meta)
return store
}

export function changeSyncMapById(client, Template, id, fields, value) {
export async function changeSyncMapById(client, Template, id, fields, value) {
if (value) fields = { [fields]: value }
return addSyncAction(client, Template, {
fields,
id,
type: `${Template.plural}/change`
})

if (Template.remote) {
return addSyncAction(client, Template, {
fields,
id,
type: `${Template.plural}/change`
})
} else {
let reasons = Object.keys(fields).map(i => `${Template.plural}/${id}/${i}`)
let meta = await addSyncAction(
client,
Template,
{
fields,
id,
type: `${Template.plural}/changed`
},
{ reasons: [...reasons] }
)
return Promise.all(
reasons.map(reason => {
return client.log.removeReason(reason, { olderThan: meta })
})
)
}
}

export function changeSyncMap(store, fields, value) {
Expand All @@ -395,11 +431,25 @@ export function changeSyncMap(store, fields, value) {
return changeSyncMapById(store.client, store, store.get().id, fields)
}

export function deleteSyncMapById(client, Template, id) {
return addSyncAction(client, Template, {
id,
type: `${Template.plural}/delete`
})
export async function deleteSyncMapById(client, Template, id) {
if (Template.remote) {
return addSyncAction(client, Template, {
id,
type: `${Template.plural}/delete`
})
} else {
let store = Template.client ? Template : Template(id, client)
if (store.get().isLoading) await store.loading
await Promise.all(
Object.keys(store.get())
.filter(i => i !== 'id' && i !== 'isLoading')
.map(key => client.log.removeReason(`${Template.plural}/${id}/${key}`))
)
return addSyncAction(client, Template, {
id,
type: `${Template.plural}/deleted`
})
}
}

export function deleteSyncMap(store) {
Expand Down
103 changes: 100 additions & 3 deletions sync-map-template/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ it('deletes maps', async () => {
expect(client.log.actions()).toEqual([])
})

it('creates and deletes local maps', async () => {
it('creates and deletes local maps on uncleaned log', async () => {
let client = new TestClient('10')
client.log.keepActions()

Expand Down Expand Up @@ -697,7 +697,6 @@ it('allows to send create action and return instance', async () => {

it('does not send subscription on local store creation', async () => {
let client = new TestClient('10')
client.log.keepActions()
await client.connect()
expect(
await client.sent(async () => {
Expand Down Expand Up @@ -768,7 +767,6 @@ it('has helper to insure that store is loaded', async () => {

it('has helper to load value', async () => {
let client = new TestClient('10')
client.log.keepActions()
await createSyncMap(client, LocalPost, {
id: '1',
title: 'A'
Expand All @@ -793,3 +791,102 @@ it('has helper to load value', async () => {
title: 'B'
})
})

it('keeps action in a log for local values', async () => {
let client = new TestClient('10')
await createSyncMap(client, LocalPost, {
category: 'first',
id: '1',
title: 'A'
})
await buildNewSyncMap(client, LocalPost, {
id: '2',
title: 'B'
})
expect(client.log.actions()).toEqual([
{
fields: { category: 'first', title: 'A' },
id: '1',
type: 'localPosts/created'
},
{
fields: { title: 'B' },
id: '2',
type: 'localPosts/created'
}
])

await changeSyncMapById(client, LocalPost, '1', { title: 'A1' })
expect(client.log.actions()).toEqual([
{
fields: { category: 'first', title: 'A' },
id: '1',
type: 'localPosts/created'
},
{
fields: { title: 'B' },
id: '2',
type: 'localPosts/created'
},
{
fields: { title: 'A1' },
id: '1',
type: 'localPosts/changed'
}
])

await changeSyncMapById(client, LocalPost, '1', { title: 'A2' })
expect(client.log.actions()).toEqual([
{
fields: { category: 'first', title: 'A' },
id: '1',
type: 'localPosts/created'
},
{
fields: { title: 'B' },
id: '2',
type: 'localPosts/created'
},
{
fields: { title: 'A2' },
id: '1',
type: 'localPosts/changed'
}
])

await changeSyncMapById(client, LocalPost, '1', { category: 'second' })
expect(client.log.actions()).toEqual([
{
fields: { title: 'B' },
id: '2',
type: 'localPosts/created'
},
{
fields: { title: 'A2' },
id: '1',
type: 'localPosts/changed'
},
{
fields: { category: 'second' },
id: '1',
type: 'localPosts/changed'
}
])

await deleteSyncMapById(client, LocalPost, '2')
expect(client.log.actions()).toEqual([
{
fields: { title: 'A2' },
id: '1',
type: 'localPosts/changed'
},
{
fields: { category: 'second' },
id: '1',
type: 'localPosts/changed'
}
])

await deleteSyncMapById(client, LocalPost, '1')
expect(client.log.actions()).toEqual([])
})
26 changes: 13 additions & 13 deletions vue/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,20 +496,20 @@ it('recreates filter on args changes', async () => {
createSyncMap(client, LocalPostStore, {
id: '1',
projectId: '1',
title: 'Y'
title: '1'
}),
createSyncMap(client, LocalPostStore, {
id: '2',
projectId: '2',
title: 'Y'
projectId: '5',
title: '2'
}),
createSyncMap(client, LocalPostStore, {
id: '3',
projectId: '1',
title: 'A'
title: '3'
})
])
expect(screen.getByTestId('test').textContent).toBe(' 0:Y 1:A')
expect(screen.getByTestId('test').textContent).toBe(' 0:1 1:3')
expect(renders).toEqual(['list', 'list', '1', '3'])

renders.splice(0, renders.length)
Expand All @@ -523,24 +523,24 @@ it('recreates filter on args changes', async () => {
renders.splice(0, renders.length)
await Promise.all([
createSyncMap(client, LocalPostStore, {
id: '1',
id: '4',
projectId: '1',
title: 'Y'
title: '4'
}),
createSyncMap(client, LocalPostStore, {
id: '2',
id: '5',
projectId: '2',
title: 'Y'
title: '5'
}),
createSyncMap(client, LocalPostStore, {
id: '3',
id: '6',
projectId: '1',
title: 'A'
title: '6'
})
])
await delay(10)
expect(screen.getByTestId('test').textContent).toBe(' 0:Y')
expect(renders).toEqual(['list', '2'])
expect(screen.getByTestId('test').textContent).toBe(' 0:5')
expect(renders).toEqual(['list', '5'])
})

it('renders authentication state', async () => {
Expand Down

0 comments on commit 9d363e0

Please sign in to comment.