Skip to content

Commit

Permalink
Allow specifying a topic when subscribing to a document (#487)
Browse files Browse the repository at this point in the history
* Modify `doc.subscribe` function to allow specifying a topic

* Add document.getValueByPath

* Specify the doc.subscribe event value for each operation

* Use `waitStubCallCount` instead of `createEmitterAndSpy` and `waitFor`

`waitFor` continuously registers the listener, which may result in
missed event detections if an event occurs before the registration.
Therefore, `waitFor` has been replaced with `waitStubCallCount`
to verify the number of times the callback function is called
and which events are executed.

* Add test that `remote-change` event is properly detected in `doc.subscribe`

* Modify the `selectPriv` method to return `TextChange` when setting the initial selectionMap

---------

Co-authored-by: Youngteac Hong <[email protected]>
  • Loading branch information
chacha912 and hackerwins authored Apr 11, 2023
1 parent 0afacc0 commit 059b20b
Show file tree
Hide file tree
Showing 22 changed files with 1,608 additions and 328 deletions.
459 changes: 459 additions & 0 deletions public/multi.html

Large diffs are not rendered by default.

90 changes: 88 additions & 2 deletions public/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ body {
background: white;
}

h2 {
margin-top: 1.6em;
}

li {
list-style: none;
}

button {
display: inline-flex;
cursor: pointer;
justify-content: center;
align-items: center;
}

#network-status span {
display: inline-block;
height: 0.8rem;
Expand Down Expand Up @@ -33,11 +48,11 @@ body {
font-weight: bold;
}

button {
#increaseButton,
#decreaseButton {
margin-right: 1em;
width: 30px;
height: 30px;
cursor: pointer;
}

#network-status:before {
Expand Down Expand Up @@ -76,3 +91,74 @@ button {
overflow-y: auto;
resize: vertical;
}

.increaseButton {
display: inline-block;
border: 1px solid #ddd;
border-radius: 10px;
padding: 0.6em 1.2em;
font-size: 1rem;
font-weight: bold;
}

.todos {
width: 300px;
background: #efefef;
border-radius: 10px;
overflow: hidden;
border: 1px solid #ddd;
}
.todoList {
margin: 0;
padding: 8px 0;
height: 160px;
box-sizing: border-box;
overflow-y: auto;
}
.todoList li {
display: flex;
padding: 10px;
font-size: 0.9em;
}
.todoList li:hover,
.todoList li:focus {
background: #e2e2e2;
}
.todoList li .itemName {
padding: 0 10px;
flex: 1;
word-break: break-all;
}
.todoList .trash {
background: transparent;
border: none;
}
.todoList .moveUp,
.todoList .moveDown {
background: #fff;
border-radius: 10px;
border: none;
margin-right: 4px;
color: #666;
}
.todoList .trash:hover,
.todoList .moveUp:hover,
.todoList .moveDown:hover {
scale: 1.1;
}
.todoNew {
display: flex;
border-top: 1px solid #ddd;
}
.todoNew .addButton {
border: none;
padding: 0 10px;
}
.todoInput {
display: inline-block;
flex: 1;
padding: 0 20px;
height: 30px;
border: none;
outline: none;
}
12 changes: 9 additions & 3 deletions src/document/change/change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
*/

import { ActorID } from '@yorkie-js-sdk/src/document/time/actor_id';
import { Operation } from '@yorkie-js-sdk/src/document/operation/operation';
import {
Operation,
InternalOpInfo,
} from '@yorkie-js-sdk/src/document/operation/operation';
import { CRDTRoot } from '@yorkie-js-sdk/src/document/crdt/root';
import { ChangeID } from '@yorkie-js-sdk/src/document/change/change_id';

Expand Down Expand Up @@ -83,10 +86,13 @@ export class Change {
/**
* `execute` executes the operations of this change to the given root.
*/
public execute(root: CRDTRoot): void {
public execute(root: CRDTRoot): Array<InternalOpInfo> {
const opInfos: Array<InternalOpInfo> = [];
for (const operation of this.operations) {
operation.execute(root);
const infos = operation.execute(root);
opInfos.push(...infos);
}
return opInfos;
}

/**
Expand Down
4 changes: 1 addition & 3 deletions src/document/crdt/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,9 @@ export class CRDTRoot {
const subPaths: Array<string> = [];
while (pair.parent) {
const createdAt = pair.element.getCreatedAt();
let subPath = pair.parent.subPathOf(createdAt);
const subPath = pair.parent.subPathOf(createdAt);
if (subPath === undefined) {
logger.fatal(`cant find the given element: ${createdAt.toIDString()}`);
} else {
subPath = subPath.replace(/[$.]/g, '\\$&');
}

subPaths.unshift(subPath!);
Expand Down
24 changes: 10 additions & 14 deletions src/document/crdt/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export class CRDTText<A extends Indexable = Indexable> extends CRDTTextElement {
editedAt: TimeTicket,
attributes?: Record<string, string>,
latestCreatedAtMapByActor?: Map<string, TimeTicket>,
): Map<string, TimeTicket> {
): [Map<string, TimeTicket>, Array<TextChange<A>>] {
const crdtTextValue = content ? CRDTTextValue.create(content) : undefined;
if (crdtTextValue && attributes) {
for (const [k, v] of Object.entries(attributes)) {
Expand Down Expand Up @@ -237,7 +237,7 @@ export class CRDTText<A extends Indexable = Indexable> extends CRDTTextElement {
this.remoteChangeLock = false;
}

return latestCreatedAtMap;
return [latestCreatedAtMap, changes];
}

/**
Expand All @@ -254,7 +254,7 @@ export class CRDTText<A extends Indexable = Indexable> extends CRDTTextElement {
range: RGATreeSplitNodeRange,
attributes: Record<string, string>,
editedAt: TimeTicket,
): void {
): Array<TextChange<A>> {
// 01. split nodes with from and to
const [, toRight] = this.rgaTreeSplit.findNodeWithSplit(range[1], editedAt);
const [, fromRight] = this.rgaTreeSplit.findNodeWithSplit(
Expand All @@ -280,7 +280,6 @@ export class CRDTText<A extends Indexable = Indexable> extends CRDTTextElement {
to: toIdx,
value: {
attributes: this.parseAttributes(attributes) as A,
content: undefined,
},
});

Expand All @@ -294,14 +293,18 @@ export class CRDTText<A extends Indexable = Indexable> extends CRDTTextElement {
this.onChangesHandler(changes);
this.remoteChangeLock = false;
}
return changes;
}

/**
* `select` stores that the given range has been selected.
*
* @internal
*/
public select(range: RGATreeSplitNodeRange, updatedAt: TimeTicket): void {
public select(
range: RGATreeSplitNodeRange,
updatedAt: TimeTicket,
): TextChange<A> | undefined {
if (this.remoteChangeLock) {
return;
}
Expand All @@ -312,6 +315,7 @@ export class CRDTText<A extends Indexable = Indexable> extends CRDTTextElement {
this.onChangesHandler([change]);
this.remoteChangeLock = false;
}
return change;
}

/**
Expand Down Expand Up @@ -445,16 +449,8 @@ export class CRDTText<A extends Indexable = Indexable> extends CRDTTextElement {
range: RGATreeSplitNodeRange,
updatedAt: TimeTicket,
): TextChange<A> | undefined {
if (!this.selectionMap.has(updatedAt.getActorID()!)) {
this.selectionMap.set(
updatedAt.getActorID()!,
Selection.of(range, updatedAt),
);
return;
}

const prevSelection = this.selectionMap.get(updatedAt.getActorID()!);
if (updatedAt.after(prevSelection!.getUpdatedAt())) {
if (!prevSelection || updatedAt.after(prevSelection!.getUpdatedAt())) {
this.selectionMap.set(
updatedAt.getActorID()!,
Selection.of(range, updatedAt),
Expand Down
Loading

0 comments on commit 059b20b

Please sign in to comment.