Skip to content

Commit

Permalink
Fix getGarbageLen to retrun correct size (#714)
Browse files Browse the repository at this point in the history
To ensure that the getGarbageLen function returns the correct length,
this commit uses a set to eliminate duplicate counting.
  • Loading branch information
devleejb committed Jan 4, 2024
1 parent 48c3ccb commit 1c65dd9
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/document/crdt/root.ts
Expand Up @@ -233,18 +233,21 @@ export class CRDTRoot {
*/
public getGarbageLen(): number {
let count = 0;
const seen = new Set<string>();

for (const createdAt of this.removedElementSetByCreatedAt) {
count++;
seen.add(createdAt);
const pair = this.elementPairMapByCreatedAt.get(createdAt)!;
if (pair.element instanceof CRDTContainer) {
pair.element.getDescendants(() => {
count++;
pair.element.getDescendants((el) => {
seen.add(el.getCreatedAt().toIDString());
return false;
});
}
}

count += seen.size;

for (const createdAt of this.elementHasRemovedNodesSetByCreatedAt) {
const pair = this.elementPairMapByCreatedAt.get(createdAt)!;
const elem = pair.element as CRDTGCElement;
Expand Down
46 changes: 46 additions & 0 deletions test/integration/gc_test.ts
Expand Up @@ -114,6 +114,52 @@ describe('Garbage Collection', function () {
assert.equal(root, clone);
});

it('getGarbageLen should return the actual number of elements garbage-collected', async function ({ task }) {
type TestDoc = { point?: { x?: number; y?: number } };
const docKey = toDocKey(`${task.name}-${new Date().getTime()}`);
const doc1 = new yorkie.Document<TestDoc>(docKey);
const doc2 = new yorkie.Document<TestDoc>(docKey);

const client1 = new yorkie.Client(testRPCAddr);
const client2 = new yorkie.Client(testRPCAddr);

await client1.activate();
await client2.activate();

// 1. initial state
await client1.attach(doc1, { isRealtimeSync: false });
doc1.update((root) => (root.point = { x: 0, y: 0 }));
await client1.sync();
await client2.attach(doc2, { isRealtimeSync: false });

// 2. client1 updates doc
doc1.update((root) => {
delete root.point;
});
assert.equal(doc1.getGarbageLen(), 3); // point, x, y

// 3. client2 updates doc
doc2.update((root) => {
delete root.point?.x;
});
assert.equal(doc2.getGarbageLen(), 1); // x

await client1.sync();
await client2.sync();
await client1.sync();

const gcNodeLen = 3; // point, x, y
assert.equal(doc1.getGarbageLen(), gcNodeLen);
assert.equal(doc2.getGarbageLen(), gcNodeLen);

// Actual garbage-collected nodes
assert.equal(doc1.garbageCollect(MaxTimeTicket), gcNodeLen);
assert.equal(doc2.garbageCollect(MaxTimeTicket), gcNodeLen);

await client1.deactivate();
await client2.deactivate();
});

it('text garbage collection test', function () {
const doc = new yorkie.Document<{ text: Text }>('test-doc');
doc.update((root) => (root.text = new Text()));
Expand Down

0 comments on commit 1c65dd9

Please sign in to comment.