mirror of
https://github.com/logos-messaging/js-waku.git
synced 2026-01-05 23:33:08 +00:00
feat(history): introduce ILocalHistory interface and refactor PersistentHistory to use composition over inheritance for history management.
This commit is contained in:
parent
454dc4a93b
commit
ca24c09688
@ -17,7 +17,37 @@ export const DEFAULT_MAX_LENGTH = 10_000;
|
|||||||
* If an array of items longer than `maxLength` is pushed, dropping will happen
|
* If an array of items longer than `maxLength` is pushed, dropping will happen
|
||||||
* at next push.
|
* at next push.
|
||||||
*/
|
*/
|
||||||
export class MemLocalHistory {
|
export interface ILocalHistory {
|
||||||
|
length: number;
|
||||||
|
push(...items: ContentMessage[]): number;
|
||||||
|
some(
|
||||||
|
predicate: (
|
||||||
|
value: ContentMessage,
|
||||||
|
index: number,
|
||||||
|
array: ContentMessage[]
|
||||||
|
) => unknown,
|
||||||
|
thisArg?: any
|
||||||
|
): boolean;
|
||||||
|
slice(start?: number, end?: number): ContentMessage[];
|
||||||
|
find(
|
||||||
|
predicate: (
|
||||||
|
value: ContentMessage,
|
||||||
|
index: number,
|
||||||
|
obj: ContentMessage[]
|
||||||
|
) => unknown,
|
||||||
|
thisArg?: any
|
||||||
|
): ContentMessage | undefined;
|
||||||
|
findIndex(
|
||||||
|
predicate: (
|
||||||
|
value: ContentMessage,
|
||||||
|
index: number,
|
||||||
|
obj: ContentMessage[]
|
||||||
|
) => unknown,
|
||||||
|
thisArg?: any
|
||||||
|
): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MemLocalHistory implements ILocalHistory {
|
||||||
private items: ContentMessage[] = [];
|
private items: ContentMessage[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
|
import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
|
||||||
|
|
||||||
import { MemLocalHistory } from "./mem_local_history.js";
|
import { ILocalHistory, MemLocalHistory } from "./mem_local_history.js";
|
||||||
import { ChannelId, ContentMessage, HistoryEntry } from "./message.js";
|
import { ChannelId, ContentMessage, HistoryEntry } from "./message.js";
|
||||||
|
|
||||||
export interface HistoryStorage {
|
export interface HistoryStorage {
|
||||||
@ -38,31 +38,73 @@ const HISTORY_STORAGE_PREFIX = "waku:sds:history:";
|
|||||||
*
|
*
|
||||||
* If no storage backend is available, this behaves like {@link MemLocalHistory}.
|
* If no storage backend is available, this behaves like {@link MemLocalHistory}.
|
||||||
*/
|
*/
|
||||||
export class PersistentHistory extends MemLocalHistory {
|
export class PersistentHistory implements ILocalHistory {
|
||||||
private readonly storage?: HistoryStorage;
|
private readonly storage?: HistoryStorage;
|
||||||
private readonly storageKey: string;
|
private readonly storageKey: string;
|
||||||
|
private readonly memory: MemLocalHistory;
|
||||||
|
|
||||||
public constructor(options: PersistentHistoryOptions) {
|
public constructor(options: PersistentHistoryOptions) {
|
||||||
super();
|
this.memory = new MemLocalHistory();
|
||||||
this.storage = options.storage ?? getDefaultHistoryStorage();
|
this.storage = options.storage ?? getDefaultHistoryStorage();
|
||||||
this.storageKey =
|
this.storageKey =
|
||||||
options.storageKey ?? `${HISTORY_STORAGE_PREFIX}${options.channelId}`;
|
options.storageKey ?? `${HISTORY_STORAGE_PREFIX}${options.channelId}`;
|
||||||
this.restore();
|
this.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override push(...items: ContentMessage[]): number {
|
public get length(): number {
|
||||||
const length = super.push(...items);
|
return this.memory.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public push(...items: ContentMessage[]): number {
|
||||||
|
const length = this.memory.push(...items);
|
||||||
this.persist();
|
this.persist();
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public some(
|
||||||
|
predicate: (
|
||||||
|
value: ContentMessage,
|
||||||
|
index: number,
|
||||||
|
array: ContentMessage[]
|
||||||
|
) => unknown,
|
||||||
|
thisArg?: any
|
||||||
|
): boolean {
|
||||||
|
return this.memory.some(predicate, thisArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public slice(start?: number, end?: number): ContentMessage[] {
|
||||||
|
return this.memory.slice(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public find(
|
||||||
|
predicate: (
|
||||||
|
value: ContentMessage,
|
||||||
|
index: number,
|
||||||
|
obj: ContentMessage[]
|
||||||
|
) => unknown,
|
||||||
|
thisArg?: any
|
||||||
|
): ContentMessage | undefined {
|
||||||
|
return this.memory.find(predicate, thisArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public findIndex(
|
||||||
|
predicate: (
|
||||||
|
value: ContentMessage,
|
||||||
|
index: number,
|
||||||
|
obj: ContentMessage[]
|
||||||
|
) => unknown,
|
||||||
|
thisArg?: any
|
||||||
|
): number {
|
||||||
|
return this.memory.findIndex(predicate, thisArg);
|
||||||
|
}
|
||||||
|
|
||||||
private persist(): void {
|
private persist(): void {
|
||||||
if (!this.storage) {
|
if (!this.storage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const payload = JSON.stringify(
|
const payload = JSON.stringify(
|
||||||
this.slice(0).map(serializeContentMessage)
|
this.memory.slice(0).map(serializeContentMessage)
|
||||||
);
|
);
|
||||||
this.storage.setItem(this.storageKey, payload);
|
this.storage.setItem(this.storageKey, payload);
|
||||||
} catch {
|
} catch {
|
||||||
@ -86,7 +128,7 @@ export class PersistentHistory extends MemLocalHistory {
|
|||||||
.map(deserializeContentMessage)
|
.map(deserializeContentMessage)
|
||||||
.filter((message): message is ContentMessage => Boolean(message));
|
.filter((message): message is ContentMessage => Boolean(message));
|
||||||
if (messages.length) {
|
if (messages.length) {
|
||||||
super.push(...messages);
|
this.memory.push(...messages);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
try {
|
try {
|
||||||
@ -153,6 +195,7 @@ const deserializeContentMessage = (
|
|||||||
BigInt(record.lamportTimestamp),
|
BigInt(record.lamportTimestamp),
|
||||||
fromHex(record.bloomFilter),
|
fromHex(record.bloomFilter),
|
||||||
content,
|
content,
|
||||||
|
[],
|
||||||
fromHex(record.retrievalHint)
|
fromHex(record.retrievalHint)
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user