Skip to content

Commit 8c0994b

Browse files
committed
[mergeable] Custom getNow function
1 parent 5ca90c2 commit 8c0994b

5 files changed

Lines changed: 51 additions & 11 deletions

File tree

‎src/@types/mergeable-store/docs.js‎

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@
2020
* @since v5.0.0
2121
*/
2222
/// mergeable-store
23+
24+
/**
25+
* The GetNow type is used to represent a function that returns the current time
26+
* in milliseconds.
27+
*
28+
* This is used internally within the mergeable-store module, but is used for
29+
* the createMergeableStore function's second optional argument to allow
30+
* applications to override the clock used to generate timestamps.
31+
* @category Stamps
32+
* @since v6.1.0
33+
*/
34+
/// GetNow
35+
2336
/**
2437
* The Hash type is used within the mergeable-store module to quickly compare
2538
* the content of two objects.
@@ -953,12 +966,21 @@
953966
* The createMergeableStore function creates a MergeableStore, and is the main
954967
* entry point into the mergeable-store module.
955968
*
956-
* There is one optional parameter which is a uniqueId for the MergeableStore.
957-
* This is used to distinguish conflicting changes made in the same millisecond
958-
* by two different MergeableStore objects as its hash is added to the end of
959-
* the HLC timestamps. Generally this can be omitted unless you have a need for
960-
* deterministic HLCs, such as in a testing scenario. Otherwise, TinyBase will
961-
* assign a unique Id to the Store at the time of creation.
969+
* There are two optional parameters which are only for testing and advanced
970+
* usage.
971+
*
972+
* The first is a uniqueId for the MergeableStore, used to distinguish
973+
* conflicting changes made in the same millisecond by two different
974+
* MergeableStore objects as its hash is added to the end of the HLC timestamps.
975+
* Generally this can be omitted unless you have a need for deterministic HLCs,
976+
* such as in a testing scenario. Otherwise, TinyBase will assign a unique Id to
977+
* the Store at the time of creation.
978+
*
979+
* Since v6.1.0, the second is a function that can be used to replace the way
980+
* the timestamp is generated for HLCs (by default JavaScript's `Date.now()`
981+
* method).
982+
* @param uniqueId An optional unique Id for the MergeableStore.
983+
* @param getNow An optional function that generates millisecond timestamps.
962984
* @returns A reference to the new MergeableStore.
963985
* @example
964986
* This example creates a MergeableStore.

‎src/@types/mergeable-store/index.d.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import type {
77
ValueOrUndefined,
88
} from '../store/index.d.ts';
99

10+
/// GetNow
11+
export type GetNow = () => number;
12+
1013
/// Hash
1114
export type Hash = number;
1215

@@ -141,4 +144,7 @@ export interface MergeableStore extends Store {
141144
}
142145

143146
/// createMergeableStore
144-
export function createMergeableStore(uniqueId?: Id): MergeableStore;
147+
export function createMergeableStore(
148+
uniqueId?: Id,
149+
getNow?: GetNow,
150+
): MergeableStore;

‎src/@types/mergeable-store/with-schemas/index.d.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import type {
2020
ValuesSchema,
2121
} from '../../store/with-schemas/index.d.ts';
2222

23+
/// GetNow
24+
export type GetNow = () => number;
25+
2326
/// Hash
2427
export type Hash = number;
2528

@@ -257,4 +260,7 @@ export interface MergeableStore<Schemas extends OptionalSchemas>
257260
}
258261

259262
/// createMergeableStore
260-
export function createMergeableStore(uniqueId?: Id): MergeableStore<NoSchemas>;
263+
export function createMergeableStore(
264+
uniqueId?: Id,
265+
getNow?: GetNow,
266+
): MergeableStore<NoSchemas>;

‎src/common/hlc.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type {Id} from '../@types/common/index.d.ts';
2+
import type {GetNow} from '../@types/mergeable-store/index.d.ts';
23
import {decode, encode} from './codec.ts';
34
import {getHash} from './hash.ts';
45
import {getUniqueId} from './index.ts';
@@ -48,6 +49,7 @@ const decodeTimeAndCounter = (
4849

4950
export const getHlcFunctions = (
5051
uniqueId?: Id,
52+
getNow: GetNow = Date.now,
5153
): [getHlc: () => Hlc, seenHlc: (remoteHlc: Hlc) => void] => {
5254
let logicalTime = 0;
5355
let lastCounter = -1;
@@ -79,7 +81,7 @@ export const getHlcFunctions = (
7981
logicalTime = mathMax(
8082
previousLogicalTime,
8183
remoteLogicalTime,
82-
(GLOBAL as any).HLC_TIME ?? Date.now(),
84+
(GLOBAL as any).HLC_TIME ?? getNow(),
8385
);
8486
lastCounter =
8587
logicalTime == previousLogicalTime

‎src/mergeable-store/index.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {Id} from '../@types/common/index.d.ts';
22
import type {
33
CellHashes,
44
ContentHashes,
5+
GetNow,
56
MergeableChanges,
67
MergeableContent,
78
MergeableStore,
@@ -147,13 +148,16 @@ const validateMergeableContent = (
147148
),
148149
);
149150

150-
export const createMergeableStore = ((uniqueId?: Id): MergeableStore => {
151+
export const createMergeableStore = ((
152+
uniqueId?: Id,
153+
getNow?: GetNow,
154+
): MergeableStore => {
151155
let listeningToRawStoreChanges = 1;
152156
let contentStampMap = newContentStampMap();
153157
let defaultingContent: 0 | 1 = 0;
154158
const touchedCells: IdSet3 = mapNew();
155159
const touchedValues: IdSet = setNew();
156-
const [getHlc, seenHlc] = getHlcFunctions(uniqueId);
160+
const [getHlc, seenHlc] = getHlcFunctions(uniqueId, getNow);
157161
const store = createStore();
158162

159163
const disableListeningToRawStoreChanges = (

0 commit comments

Comments
 (0)