Skip to content

Commit

Permalink
Merge pull request #449 from streamich/demos-2
Browse files Browse the repository at this point in the history
Demos 2
  • Loading branch information
streamich authored Nov 20, 2023
2 parents 450c7fe + 008de8d commit d4dc0c4
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 7 deletions.
63 changes: 63 additions & 0 deletions src/server/__tests__/blocks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,4 +422,67 @@ describe('blocks.*', () => {
});
});
});

describe('blocks.get', () => {
test('returns whole history when block is loaded', async () => {
const {client} = setup();
const model = Model.withLogicalClock();
model.api.root({
text: 'Hell',
});
const patch1 = model.api.flush();
await client.call('blocks.create', {
id: 'my-block',
patches: [
{
seq: 0,
created: Date.now(),
blob: patch1.toBinary(),
},
],
});
model.api.str(['text']).ins(4, 'o');
const patch2 = model.api.flush();
model.api.obj([]).set({
age: 26,
});
const patch3 = model.api.flush();
await client.call('blocks.edit', {
id: 'my-block',
patches: [
{
seq: 1,
created: Date.now(),
blob: patch2.toBinary(),
},
{
seq: 2,
created: Date.now(),
blob: patch3.toBinary(),
},
],
});
const result = await client.call('blocks.get', {id: 'my-block'});
expect(result).toMatchObject({
block: expect.any(Object),
patches: [
{
seq: 0,
created: expect.any(Number),
blob: patch1.toBinary(),
},
{
seq: 1,
created: expect.any(Number),
blob: patch2.toBinary(),
},
{
seq: 2,
created: expect.any(Number),
blob: patch3.toBinary(),
},
],
});
});
});
});
15 changes: 11 additions & 4 deletions src/server/routes/blocks/methods/get.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {RoutesBase, TypeRouter} from '../../../../json-type/system/TypeRouter';
import type {RouteDeps} from '../../types';
import type {Block, BlockId} from '../schema';
import type {Block, BlockId, BlockPatch} from '../schema';

export const get =
({services}: RouteDeps) =>
Expand All @@ -14,7 +14,13 @@ export const get =
}),
);

const Response = t.Object(t.prop('block', t.Ref<typeof Block>('Block').options({})));
const Response = t.Object(
t.prop('block', t.Ref<typeof Block>('Block').options({})),
t.prop('patches', t.Array(t.Ref<typeof BlockPatch>('BlockPatch'))).options({
title: 'Patches',
description: 'The list of all patches.',
}),
);

const Func = t
.Function(Request, Response)
Expand All @@ -24,9 +30,10 @@ export const get =
description: 'Fetches a block by ID.',
})
.implement(async ({id}) => {
const {block} = await services.blocks.get(id);
const {block, patches} = await services.blocks.get(id);
return {
block: block,
block,
patches,
};
});

Expand Down
16 changes: 13 additions & 3 deletions src/server/services/blocks/BlocksServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import {StorePatch} from './types';
import {RpcError, RpcErrorCodes} from '../../../reactive-rpc/common/rpc/caller';
import type {Services} from '../Services';

const BLOCK_TTL = 1000 * 60 * 20; // 20 minutes
const BLOCK_TTL = 1000 * 60 * 60; // 1 hour

const validatePatches = (patches: StorePatch[]) => {
for (const patch of patches) {
if (patch.blob.length > 2000) throw RpcError.validation('patch blob too large');
if (patch.seq > 500_000) throw RpcError.validation('patch seq too large');
}
};

export class BlocksServices {
protected readonly store = new MemoryStore();
Expand All @@ -13,6 +20,7 @@ export class BlocksServices {
public async create(id: string, patches: StorePatch[]) {
this.maybeGc();
const {store} = this;
validatePatches(patches);
const {block} = await store.create(id, patches);
const data = {
block,
Expand All @@ -29,8 +37,9 @@ export class BlocksServices {
const {store} = this;
const result = await store.get(id);
if (!result) throw RpcError.fromCode(RpcErrorCodes.NOT_FOUND);
const patches = await store.history(id, 0, result.block.seq);
const {block} = result;
return {block};
return {block, patches};
}

public async remove(id: string) {
Expand All @@ -47,12 +56,13 @@ export class BlocksServices {
return {patches};
}

public async edit(id: string, patches: any[]) {
public async edit(id: string, patches: StorePatch[]) {
this.maybeGc();
if (!Array.isArray(patches)) throw RpcError.validation('patches must be an array');
if (!patches.length) throw RpcError.validation('patches must not be empty');
const seq = patches[0].seq;
const {store} = this;
validatePatches(patches);
const {block} = await store.edit(id, patches);
this.services.pubsub.publish(`__block:${id}`, {patches}).catch((error) => {
// tslint:disable-next-line:no-console
Expand Down

0 comments on commit d4dc0c4

Please sign in to comment.