diff --git a/package.json b/package.json index 0f3f39c..b0725b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ucla-irl/ndnts-aux", - "version": "1.0.9", + "version": "1.0.10", "description": "NDNts Auxiliary Package for Web and Deno", "scripts": { "test": "deno test --no-check", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f941cd6..24e0680 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,15 +100,15 @@ packages: /@types/imap@0.8.40: resolution: {integrity: sha512-kWFwOc88CGwWZlHqCnZiceS6EralsAHdjpQyk1+fIA875NQdIHvLpdD5NU3Pi1yZ8FKFdOF81UDNAo8/XS6HiQ==} dependencies: - '@types/node': 20.11.7 + '@types/node': 20.11.8 dev: true /@types/minimalistic-assert@1.0.3: resolution: {integrity: sha512-Ku87cam4YxiXcEpeUemo+vO8QWGQ7U2CwEEcLcYFhxG8b4CK8gWxSX/oWjePWKwqPaWWxxVqXAdAjGdlJtVzDA==} dev: true - /@types/node@20.11.7: - resolution: {integrity: sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==} + /@types/node@20.11.8: + resolution: {integrity: sha512-i7omyekpPTNdv4Jb/Rgqg0RU8YqLcNsI12quKSDkRXNfx7Wxdm6HhK1awT3xTgEkgxPn3bvnSpiEAc7a7Lpyow==} dependencies: undici-types: 5.26.5 dev: true @@ -116,7 +116,7 @@ packages: /@types/nodemailer@6.4.14: resolution: {integrity: sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==} dependencies: - '@types/node': 20.11.7 + '@types/node': 20.11.8 dev: true /@types/retry@0.12.5: @@ -134,7 +134,7 @@ packages: /@types/ws@8.5.10: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} dependencies: - '@types/node': 20.11.7 + '@types/node': 20.11.8 dev: true /@yoursunny/asn1@0.0.20200718: @@ -722,7 +722,7 @@ packages: '@ndnts-nightly.ndn.today/endpoint.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/endpoint.tgz} name: '@ndn/endpoint' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/fw': '@ndnts-nightly.ndn.today/fw.tgz' '@ndn/packet': '@ndnts-nightly.ndn.today/packet.tgz' @@ -735,7 +735,7 @@ packages: '@ndnts-nightly.ndn.today/fw.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/fw.tgz} name: '@ndn/fw' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/packet': '@ndnts-nightly.ndn.today/packet.tgz' '@ndn/util': '@ndnts-nightly.ndn.today/util.tgz' @@ -752,7 +752,7 @@ packages: '@ndnts-nightly.ndn.today/keychain.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/keychain.tgz} name: '@ndn/keychain' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/naming-convention2': '@ndnts-nightly.ndn.today/naming-convention2.tgz' '@ndn/packet': '@ndnts-nightly.ndn.today/packet.tgz' @@ -769,7 +769,7 @@ packages: '@ndnts-nightly.ndn.today/l3face.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/l3face.tgz} name: '@ndn/l3face' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/fw': '@ndnts-nightly.ndn.today/fw.tgz' '@ndn/lp': '@ndnts-nightly.ndn.today/lp.tgz' @@ -789,7 +789,7 @@ packages: '@ndnts-nightly.ndn.today/lp.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/lp.tgz} name: '@ndn/lp' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/packet': '@ndnts-nightly.ndn.today/packet.tgz' '@ndn/tlv': '@ndnts-nightly.ndn.today/tlv.tgz' @@ -801,7 +801,7 @@ packages: '@ndnts-nightly.ndn.today/naming-convention2.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/naming-convention2.tgz} name: '@ndn/naming-convention2' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/packet': '@ndnts-nightly.ndn.today/packet.tgz' '@ndn/tlv': '@ndnts-nightly.ndn.today/tlv.tgz' @@ -812,7 +812,7 @@ packages: '@ndnts-nightly.ndn.today/ndncert.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/ndncert.tgz} name: '@ndn/ndncert' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/endpoint': '@ndnts-nightly.ndn.today/endpoint.tgz' '@ndn/keychain': '@ndnts-nightly.ndn.today/keychain.tgz' @@ -836,7 +836,7 @@ packages: '@ndnts-nightly.ndn.today/ndnsec.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/ndnsec.tgz} name: '@ndn/ndnsec' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/keychain': '@ndnts-nightly.ndn.today/keychain.tgz' '@ndn/packet': '@ndnts-nightly.ndn.today/packet.tgz' @@ -851,7 +851,7 @@ packages: '@ndnts-nightly.ndn.today/nfdmgmt.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/nfdmgmt.tgz} name: '@ndn/nfdmgmt' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/endpoint': '@ndnts-nightly.ndn.today/endpoint.tgz' '@ndn/fw': '@ndnts-nightly.ndn.today/fw.tgz' @@ -867,7 +867,7 @@ packages: '@ndnts-nightly.ndn.today/node-transport.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/node-transport.tgz} name: '@ndn/node-transport' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/l3face': '@ndnts-nightly.ndn.today/l3face.tgz' event-iterator: 2.0.0 @@ -880,7 +880,7 @@ packages: '@ndnts-nightly.ndn.today/packet.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/packet.tgz} name: '@ndn/packet' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/tlv': '@ndnts-nightly.ndn.today/tlv.tgz' '@ndn/util': '@ndnts-nightly.ndn.today/util.tgz' @@ -893,7 +893,7 @@ packages: '@ndnts-nightly.ndn.today/rdr.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/rdr.tgz} name: '@ndn/rdr' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/endpoint': '@ndnts-nightly.ndn.today/endpoint.tgz' '@ndn/naming-convention2': '@ndnts-nightly.ndn.today/naming-convention2.tgz' @@ -905,7 +905,7 @@ packages: '@ndnts-nightly.ndn.today/repo-api.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/repo-api.tgz} name: '@ndn/repo-api' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/l3face': '@ndnts-nightly.ndn.today/l3face.tgz' '@ndn/naming-convention2': '@ndnts-nightly.ndn.today/naming-convention2.tgz' @@ -926,7 +926,7 @@ packages: '@ndnts-nightly.ndn.today/segmented-object.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/segmented-object.tgz} name: '@ndn/segmented-object' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/endpoint': '@ndnts-nightly.ndn.today/endpoint.tgz' '@ndn/fw': '@ndnts-nightly.ndn.today/fw.tgz' @@ -947,7 +947,7 @@ packages: '@ndnts-nightly.ndn.today/sync.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/sync.tgz} name: '@ndn/sync' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/endpoint': '@ndnts-nightly.ndn.today/endpoint.tgz' '@ndn/naming-convention2': '@ndnts-nightly.ndn.today/naming-convention2.tgz' @@ -971,7 +971,7 @@ packages: '@ndnts-nightly.ndn.today/tlv.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/tlv.tgz} name: '@ndn/tlv' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/util': '@ndnts-nightly.ndn.today/util.tgz' mnemonist: 0.39.7 @@ -982,7 +982,7 @@ packages: '@ndnts-nightly.ndn.today/util.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/util.tgz} name: '@ndn/util' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 engines: {node: ^18.18.0 || ^20.0.0 || ^21.0.0} dependencies: '@types/minimalistic-assert': 1.0.3 @@ -994,7 +994,7 @@ packages: '@ndnts-nightly.ndn.today/ws-transport.tgz': resolution: {tarball: https://ndnts-nightly.ndn.today/ws-transport.tgz} name: '@ndn/ws-transport' - version: 0.0.20240122-nightly-4ebab5b + version: 0.0.20240124-nightly-37c6054 dependencies: '@ndn/l3face': '@ndnts-nightly.ndn.today/l3face.tgz' '@types/ws': 8.5.10 diff --git a/src/adaptors/yjs-state-manager.ts b/src/adaptors/yjs-state-manager.ts index 646581d..66d3ac4 100644 --- a/src/adaptors/yjs-state-manager.ts +++ b/src/adaptors/yjs-state-manager.ts @@ -8,7 +8,7 @@ const SnapshotKey = 'localSnapshot'; * YjsStateManager manages updates transported by SyncAgent. * It receives and emits updates, encodes and loads local state as updates. */ -export class YjsStateManager { +export class YjsStateManager implements AsyncDisposable { private readonly callback = this.docUpdateHandler.bind(this); private counter = 0; @@ -21,11 +21,15 @@ export class YjsStateManager { doc.on('update', this.callback); } - public destroy() { - this.saveLocalSnapshot(this.getState()); + public async destroy() { + await this.saveLocalSnapshot(this.getState()); this.doc.off('update', this.callback); } + async [Symbol.asyncDispose]() { + return await this.destroy(); + } + private docUpdateHandler(_update: Uint8Array, origin: undefined) { if (origin !== this) { // This condition must be true this.counter += 1; diff --git a/src/sync-agent/sync-agent.ts b/src/sync-agent/sync-agent.ts index 2b6dcc4..27c76ee 100644 --- a/src/sync-agent/sync-agent.ts +++ b/src/sync-agent/sync-agent.ts @@ -12,7 +12,7 @@ import { panic } from '../utils/panic.ts'; export type ChannelType = 'update' | 'blob' | 'status' | 'blobUpdate'; const AllChannelValues = ['update', 'blob', 'status', 'blobUpdate']; -export class SyncAgent { +export class SyncAgent implements AsyncDisposable { private _ready = false; readonly listeners: { [key: string]: (content: Uint8Array, id: Name) => void } = {}; readonly producer; @@ -56,13 +56,17 @@ export class SyncAgent { }); } - public destroy() { - this.atLeastOnce.destroy(); - this.latestOnly.destroy(); + public async destroy() { + await this.atLeastOnce.destroy(); + await this.latestOnly.destroy(); this.trafficAttractor.close(); this.producer.close(); } + async [Symbol.asyncDispose]() { + return await this.destroy(); + } + public reset() { this.atLeastOnce.reset(); this.latestOnly.reset(); diff --git a/src/utils/name-lit.ts b/src/utils/name-lit.ts index fe947af..3a0562b 100644 --- a/src/utils/name-lit.ts +++ b/src/utils/name-lit.ts @@ -4,6 +4,14 @@ import { Encoder, NNI } from '@ndn/tlv'; /** * NDN Name generator for test. Allows to use tag literals to generate NDN name from boilerplate. * Designed for unit tests only. Do not use in production, as it is slow and not guaranteed to reflect the latest spec. + * + * @remarks + * + * 1. Alternative URI only works for templates, e.g. `` name`/aa/seg=${1}` ``. + * 2. Do not try to fool this function on purpuse. It is designed for test use only and + * does not handle corner cases at all. + * For example, `` name`/8=seg=${0}` ``. + * * @param templates Name boilerplate * @param values Values */ diff --git a/src/workspace/workspace.ts b/src/workspace/workspace.ts index 1ea0de5..5e6162f 100644 --- a/src/workspace/workspace.ts +++ b/src/workspace/workspace.ts @@ -5,7 +5,7 @@ import { encodeSyncState, parseSyncState, SyncAgent } from '../sync-agent/mod.ts import { NdnSvsAdaptor, YjsStateManager } from '../adaptors/mod.ts'; import * as Y from 'yjs'; -export class Workspace { +export class Workspace implements AsyncDisposable { private constructor( public readonly nodeId: Name, public readonly persistStore: Storage, @@ -79,10 +79,16 @@ export class Workspace { this.syncAgent.fire(); } - public destroy() { + public async destroy() { this.syncAgent.ready = false; - this.yjsSnapshotMgr.destroy(); - this.syncAgent.destroy(); + await Promise.all([ + this.yjsSnapshotMgr.destroy(), + this.syncAgent.destroy(), + ]); // persistStore is not created by workspace } + + async [Symbol.asyncDispose]() { + return await this.destroy(); + } }