Skip to content

Commit

Permalink
Minor tweaks to @matter/general (#1523)
Browse files Browse the repository at this point in the history
Mostly small fixes.  Includes a small extension to storage to support snapshotting.
  • Loading branch information
lauckhart authored Dec 15, 2024
1 parent 35c2555 commit 2948a38
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 18 deletions.
7 changes: 1 addition & 6 deletions packages/general/src/environment/Environmental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,14 @@ export namespace Environmental {
/**
* An "environmental service" is an object available via {@link Environment.get}.
*
* Any object may be an environmental service. This methods in this interface are optional.
* Any object may be an environmental service. The methods in this interface are optional.
*/
export interface Service {
/**
* Asynchronous construction, respected by {@link Environment.load}.
*/
construction?: Promise<any>;

/**
* Asynchronous destruction. Invoked by the environment when it is destroyed.
*/
[Symbol.asyncDispose]?: () => Promise<any>;

/**
* Standard diagnostic presentation.
*/
Expand Down
9 changes: 3 additions & 6 deletions packages/general/src/environment/RuntimeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const logger = Logger.get("Runtime");
* Handles lifecycle management of other components.
*/
export class RuntimeService implements Multiplex {
#env: Environment;
#workers = new Set<RuntimeService.Worker>();
#cancelled = new Set<RuntimeService.Worker>();
#workerDeleted = Observable<[]>();
Expand All @@ -29,6 +30,7 @@ export class RuntimeService implements Multiplex {
#crashed = Observable<[cause: any]>();

constructor(environment: Environment) {
this.#env = environment;
environment.set(RuntimeService, this);
DiagnosticSource.add(this);
}
Expand Down Expand Up @@ -79,12 +81,6 @@ export class RuntimeService implements Multiplex {
break;
}
});
} else if (worker.then) {
if (worker.then) {
Promise.resolve(worker)
.catch(error => this.#crash(error))
.finally(() => this.delete(worker));
}
}
}

Expand Down Expand Up @@ -193,6 +189,7 @@ export class RuntimeService implements Multiplex {
async close() {
this.cancel();
await this.inactive;
this.#env.delete(RuntimeService, this);
DiagnosticSource.delete(this);
}

Expand Down
21 changes: 20 additions & 1 deletion packages/general/src/storage/Storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Copyright 2022-2024 Matter.js Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { MatterError } from "../MatterError.js";
import { ImplementationError, MatterError } from "../MatterError.js";
import { MaybePromise } from "../util/Promises.js";
import { SupportedStorageTypes } from "./StringifyTools.js";

Expand All @@ -26,6 +26,25 @@ export interface Storage {
clearAll(contexts: string[]): MaybePromise<void>;
}

/**
* Extended interface for storage that supports snapshotting.
*/
export interface CloneableStorage {
clone(): MaybePromise<Storage>;
}

export namespace CloneableStorage {
export function is<T extends {}>(storage: T): storage is T & CloneableStorage {
return "clone" in storage && typeof storage.clone === "function";
}

export function assert<T extends {}>(storage: T): asserts storage is T & CloneableStorage {
if (!is(storage)) {
throw new ImplementationError("Storage does not support required snapshotting function");
}
}
}

// This extra class is needed because of https://github.com/microsoft/TypeScript/issues/57905 in order
// to have the generics typing support on the "get" method and can be removed when the TS issue is fixed
// or we remove the legacy API.
Expand Down
11 changes: 9 additions & 2 deletions packages/general/src/storage/StorageBackendMemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { StorageError, SyncStorage } from "./Storage.js";
import { deepCopy } from "#util/DeepCopy.js";
import { CloneableStorage, StorageError, SyncStorage } from "./Storage.js";
import { SupportedStorageTypes } from "./StringifyTools.js";

export class StorageBackendMemory extends SyncStorage {
export class StorageBackendMemory extends SyncStorage implements CloneableStorage {
protected isInitialized = false;

constructor(protected store: any = {}) {
Expand Down Expand Up @@ -37,6 +38,12 @@ export class StorageBackendMemory extends SyncStorage {
// nothing else to do
}

clone() {
const clone = new StorageBackendMemory(deepCopy(this.store));
clone.initialize();
return clone;
}

close() {
this.isInitialized = false;
// nothing to do
Expand Down
4 changes: 2 additions & 2 deletions packages/general/src/util/Construction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ export function Construction<const T extends Constructable>(

case Lifecycle.Status.Destroying:
if (newStatus !== Lifecycle.Status.Destroyed) {
throw new ImplementationError("Cannog change status because destruction is ongoing");
throw new ImplementationError("Cannot change status because destruction is ongoing");
}
break;

Expand Down Expand Up @@ -691,7 +691,7 @@ export namespace Construction {
}

const crashed = Object.values(subjectArray).filter(
backing => backing.construction.status === Lifecycle.Status.Crashed,
subject => subject.construction.status === Lifecycle.Status.Crashed,
);
if (crashed.length) {
let error;
Expand Down
2 changes: 1 addition & 1 deletion packages/general/src/util/String.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function camelize(name: string, upperFirst = false) {
.join("");

// Special case so "100ths" doesn't become "100Ths" which is formally correct but goofy
result = result.replace(/(\d+)Ths/i, "$1ths");
result = result.replace(/(\d)Ths/i, "$1ths");

return result;
}
Expand Down

0 comments on commit 2948a38

Please sign in to comment.