mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-03 05:26:07 +00:00
Merge pull request #233 from MARCROCK22/main
encode and decode data in cache
This commit is contained in:
commit
c54091b2b4
34
src/cache/adapters/default.ts
vendored
34
src/cache/adapters/default.ts
vendored
@ -1,11 +1,27 @@
|
|||||||
import type { Adapter } from './types';
|
import type { Adapter } from './types';
|
||||||
|
|
||||||
export class MemoryAdapter implements Adapter {
|
export interface MemoryAdapterOptions<T> {
|
||||||
|
encode(data: any): T;
|
||||||
|
decode(data: T): unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MemoryAdapter<T> implements Adapter {
|
||||||
isAsync = false;
|
isAsync = false;
|
||||||
|
|
||||||
readonly storage = new Map<string, string>();
|
readonly storage = new Map<string, T>();
|
||||||
readonly relationships = new Map<string, string[]>();
|
readonly relationships = new Map<string, string[]>();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public options: MemoryAdapterOptions<T> = {
|
||||||
|
encode(data) {
|
||||||
|
return JSON.stringify(data) as T;
|
||||||
|
},
|
||||||
|
decode(data) {
|
||||||
|
return JSON.parse(data as string);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
|
||||||
scan(query: string, keys?: false): any[];
|
scan(query: string, keys?: false): any[];
|
||||||
scan(query: string, keys: true): string[];
|
scan(query: string, keys: true): string[];
|
||||||
scan(query: string, keys = false) {
|
scan(query: string, keys = false) {
|
||||||
@ -13,7 +29,7 @@ export class MemoryAdapter implements Adapter {
|
|||||||
const sq = query.split('.');
|
const sq = query.split('.');
|
||||||
for (const [key, value] of this.storage.entries()) {
|
for (const [key, value] of this.storage.entries()) {
|
||||||
if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) {
|
if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) {
|
||||||
values.push(keys ? key : JSON.parse(value));
|
values.push(keys ? key : this.options.decode(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,24 +40,24 @@ export class MemoryAdapter implements Adapter {
|
|||||||
return keys
|
return keys
|
||||||
.map(x => {
|
.map(x => {
|
||||||
const data = this.storage.get(x);
|
const data = this.storage.get(x);
|
||||||
return data ? JSON.parse(data) : null;
|
return data ? this.options.decode(data) : null;
|
||||||
})
|
})
|
||||||
.filter(x => x);
|
.filter(x => x);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(keys: string) {
|
get(keys: string) {
|
||||||
const data = this.storage.get(keys);
|
const data = this.storage.get(keys);
|
||||||
return data ? JSON.parse(data) : null;
|
return data ? this.options.decode(data) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bulkSet(keys: [string, any][]) {
|
bulkSet(keys: [string, any][]) {
|
||||||
for (const [key, value] of keys) {
|
for (const [key, value] of keys) {
|
||||||
this.storage.set(key, JSON.stringify(value));
|
this.storage.set(key, this.options.encode(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set(key: string, data: any) {
|
set(key: string, data: any) {
|
||||||
this.storage.set(key, JSON.stringify(data));
|
this.storage.set(key, this.options.encode(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
bulkPatch(updateOnly: boolean, keys: [string, any][]) {
|
bulkPatch(updateOnly: boolean, keys: [string, any][]) {
|
||||||
@ -52,7 +68,7 @@ export class MemoryAdapter implements Adapter {
|
|||||||
}
|
}
|
||||||
this.storage.set(
|
this.storage.set(
|
||||||
key,
|
key,
|
||||||
Array.isArray(value) ? JSON.stringify(value) : JSON.stringify({ ...(oldData ?? {}), ...value }),
|
Array.isArray(value) ? this.options.encode(value) : this.options.encode({ ...(oldData ?? {}), ...value }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +80,7 @@ export class MemoryAdapter implements Adapter {
|
|||||||
}
|
}
|
||||||
this.storage.set(
|
this.storage.set(
|
||||||
keys,
|
keys,
|
||||||
Array.isArray(data) ? JSON.stringify(data) : JSON.stringify({ ...(oldData ?? {}), ...data }),
|
Array.isArray(data) ? this.options.encode(data) : this.options.encode({ ...(oldData ?? {}), ...data }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
src/cache/adapters/limited.ts
vendored
35
src/cache/adapters/limited.ts
vendored
@ -7,7 +7,7 @@ export interface ResourceLimitedMemoryAdapter {
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LimitedMemoryAdapterOptions {
|
export interface LimitedMemoryAdapterOptions<T> {
|
||||||
default?: ResourceLimitedMemoryAdapter;
|
default?: ResourceLimitedMemoryAdapter;
|
||||||
|
|
||||||
guild?: ResourceLimitedMemoryAdapter;
|
guild?: ResourceLimitedMemoryAdapter;
|
||||||
@ -26,24 +26,33 @@ export interface LimitedMemoryAdapterOptions {
|
|||||||
thread?: ResourceLimitedMemoryAdapter;
|
thread?: ResourceLimitedMemoryAdapter;
|
||||||
overwrite?: ResourceLimitedMemoryAdapter;
|
overwrite?: ResourceLimitedMemoryAdapter;
|
||||||
message?: ResourceLimitedMemoryAdapter;
|
message?: ResourceLimitedMemoryAdapter;
|
||||||
|
|
||||||
|
encode(data: any): T;
|
||||||
|
decode(data: T): unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LimitedMemoryAdapter implements Adapter {
|
export class LimitedMemoryAdapter<T> implements Adapter {
|
||||||
isAsync = false;
|
isAsync = false;
|
||||||
|
|
||||||
readonly storage = new Map<string, LimitedCollection<string, string>>();
|
readonly storage = new Map<string, LimitedCollection<string, T>>();
|
||||||
readonly relationships = new Map<string, Map<string, string[]>>();
|
readonly relationships = new Map<string, Map<string, string[]>>();
|
||||||
|
|
||||||
options: MakeRequired<LimitedMemoryAdapterOptions, 'default'>;
|
options: MakeRequired<LimitedMemoryAdapterOptions<T>, 'default'>;
|
||||||
|
|
||||||
constructor(options: LimitedMemoryAdapterOptions) {
|
constructor(options: LimitedMemoryAdapterOptions<T>) {
|
||||||
this.options = MergeOptions(
|
this.options = MergeOptions(
|
||||||
{
|
{
|
||||||
default: {
|
default: {
|
||||||
expire: undefined,
|
expire: undefined,
|
||||||
limit: Number.POSITIVE_INFINITY,
|
limit: Number.POSITIVE_INFINITY,
|
||||||
},
|
},
|
||||||
} satisfies LimitedMemoryAdapterOptions,
|
encode(data) {
|
||||||
|
return JSON.stringify(data) as T;
|
||||||
|
},
|
||||||
|
decode(data) {
|
||||||
|
return JSON.parse(data as string);
|
||||||
|
},
|
||||||
|
} satisfies LimitedMemoryAdapterOptions<T>,
|
||||||
options,
|
options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -56,7 +65,7 @@ export class LimitedMemoryAdapter implements Adapter {
|
|||||||
for (const iterator of [...this.storage.values()].flatMap(x => x.entries()))
|
for (const iterator of [...this.storage.values()].flatMap(x => x.entries()))
|
||||||
for (const [key, value] of iterator) {
|
for (const [key, value] of iterator) {
|
||||||
if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) {
|
if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) {
|
||||||
values.push(keys ? key : JSON.parse(value.value));
|
values.push(keys ? key : this.options.decode(value.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +77,14 @@ export class LimitedMemoryAdapter implements Adapter {
|
|||||||
return keys
|
return keys
|
||||||
.map(key => {
|
.map(key => {
|
||||||
const data = iterator.find(x => x.has(key))?.get(key);
|
const data = iterator.find(x => x.has(key))?.get(key);
|
||||||
return data ? JSON.parse(data) : null;
|
return data ? this.options.decode(data) : null;
|
||||||
})
|
})
|
||||||
.filter(x => x);
|
.filter(x => x);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(keys: string) {
|
get(keys: string) {
|
||||||
const data = [...this.storage.values()].find(x => x.has(keys))?.get(keys);
|
const data = [...this.storage.values()].find(x => x.has(keys))?.get(keys);
|
||||||
return data ? JSON.parse(data) : null;
|
return data ? this.options.decode(data) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private __set(key: string, data: any) {
|
private __set(key: string, data: any) {
|
||||||
@ -87,9 +96,11 @@ export class LimitedMemoryAdapter implements Adapter {
|
|||||||
namespace,
|
namespace,
|
||||||
new LimitedCollection({
|
new LimitedCollection({
|
||||||
expire:
|
expire:
|
||||||
this.options[key.split('.')[0] as keyof LimitedMemoryAdapterOptions]?.expire ?? this.options.default.expire,
|
this.options[key.split('.')[0] as Exclude<keyof LimitedMemoryAdapterOptions<T>, 'decode' | 'encode'>]
|
||||||
|
?.expire ?? this.options.default.expire,
|
||||||
limit:
|
limit:
|
||||||
this.options[key.split('.')[0] as keyof LimitedMemoryAdapterOptions]?.limit ?? this.options.default.limit,
|
this.options[key.split('.')[0] as Exclude<keyof LimitedMemoryAdapterOptions<T>, 'decode' | 'encode'>]
|
||||||
|
?.limit ?? this.options.default.limit,
|
||||||
resetOnDemand: true,
|
resetOnDemand: true,
|
||||||
onDelete(k) {
|
onDelete(k) {
|
||||||
const relationshipNamespace = key.split('.')[0];
|
const relationshipNamespace = key.split('.')[0];
|
||||||
@ -126,7 +137,7 @@ export class LimitedMemoryAdapter implements Adapter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.storage.get(namespace)!.set(key, JSON.stringify(data));
|
this.storage.get(namespace)!.set(key, this.options.encode(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
bulkSet(keys: [string, any][]) {
|
bulkSet(keys: [string, any][]) {
|
||||||
|
@ -141,7 +141,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
protected async onPacket(shardId: number, packet: GatewayDispatchPayload) {
|
protected async onPacket(shardId: number, packet: GatewayDispatchPayload) {
|
||||||
Promise.allSettled([
|
Promise.allSettled([
|
||||||
this.events?.runEvent('RAW', this, packet, shardId, false),
|
this.events?.runEvent('RAW', this, packet, shardId, false),
|
||||||
this.collectors.run('RAW', packet),
|
this.collectors.run('RAW', packet, this),
|
||||||
]); //ignore promise
|
]); //ignore promise
|
||||||
switch (packet.t) {
|
switch (packet.t) {
|
||||||
//// Cases where we must obtain the old data before updating
|
//// Cases where we must obtain the old data before updating
|
||||||
|
@ -2,6 +2,8 @@ import { randomUUID } from 'node:crypto';
|
|||||||
import type { Awaitable, CamelCase } from '../common';
|
import type { Awaitable, CamelCase } from '../common';
|
||||||
import type { CallbackEventHandler, CustomEventsKeys, GatewayEvents } from '../events';
|
import type { CallbackEventHandler, CustomEventsKeys, GatewayEvents } from '../events';
|
||||||
import { error } from 'node:console';
|
import { error } from 'node:console';
|
||||||
|
import * as RawEvents from '../events/hooks';
|
||||||
|
import type { UsingClient } from '../commands';
|
||||||
|
|
||||||
export type AllClientEvents = CustomEventsKeys | GatewayEvents;
|
export type AllClientEvents = CustomEventsKeys | GatewayEvents;
|
||||||
export type ParseClientEventName<T extends AllClientEvents> = T extends CustomEventsKeys ? T : CamelCase<T>;
|
export type ParseClientEventName<T extends AllClientEvents> = T extends CustomEventsKeys ? T : CamelCase<T>;
|
||||||
@ -98,11 +100,14 @@ export class Collectors {
|
|||||||
/**@internal */
|
/**@internal */
|
||||||
async run<T extends AllClientEvents>(
|
async run<T extends AllClientEvents>(
|
||||||
name: T,
|
name: T,
|
||||||
data: Awaited<Parameters<CallbackEventHandler[ParseClientEventName<T>]>[0]>,
|
raw: Awaited<Parameters<CallbackEventHandler[ParseClientEventName<T>]>[0]>,
|
||||||
|
client: UsingClient,
|
||||||
) {
|
) {
|
||||||
const collectors = this.values.get(name);
|
const collectors = this.values.get(name);
|
||||||
if (!collectors) return;
|
if (!collectors) return;
|
||||||
|
|
||||||
|
const data = RawEvents[name]?.(client, raw as never) ?? raw;
|
||||||
|
|
||||||
for (const i of collectors) {
|
for (const i of collectors) {
|
||||||
if (await i.options.filter(data as never)) {
|
if (await i.options.filter(data as never)) {
|
||||||
i.idle?.refresh();
|
i.idle?.refresh();
|
||||||
|
@ -357,7 +357,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
protected async onPacket(packet: GatewayDispatchPayload, shardId: number) {
|
protected async onPacket(packet: GatewayDispatchPayload, shardId: number) {
|
||||||
Promise.allSettled([
|
Promise.allSettled([
|
||||||
this.events?.runEvent('RAW', this, packet, shardId, false),
|
this.events?.runEvent('RAW', this, packet, shardId, false),
|
||||||
this.collectors.run('RAW', packet),
|
this.collectors.run('RAW', packet, this),
|
||||||
]); //ignore promise
|
]); //ignore promise
|
||||||
switch (packet.t) {
|
switch (packet.t) {
|
||||||
//// Cases where we must obtain the old data before updating
|
//// Cases where we must obtain the old data before updating
|
||||||
|
@ -111,7 +111,7 @@ export class EventHandler extends BaseHandler {
|
|||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.runEvent(args[0].t as never, args[1], args[0].d, args[2]),
|
this.runEvent(args[0].t as never, args[1], args[0].d, args[2]),
|
||||||
this.client.collectors.run(args[0].t as never, args[0].d as never),
|
this.client.collectors.run(args[0].t as never, args[0].d as never, this.client),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,15 +150,15 @@ export class EventHandler extends BaseHandler {
|
|||||||
async runCustom<T extends CustomEventsKeys>(name: T, ...args: Parameters<CustomEvents[T]>) {
|
async runCustom<T extends CustomEventsKeys>(name: T, ...args: Parameters<CustomEvents[T]>) {
|
||||||
const Event = this.values[name];
|
const Event = this.values[name];
|
||||||
if (!Event) {
|
if (!Event) {
|
||||||
return this.client.collectors.run(name, args as never);
|
return this.client.collectors.run(name, args as never, this.client);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (Event.data.once && Event.fired) {
|
if (Event.data.once && Event.fired) {
|
||||||
return this.client.collectors.run(name, args as never);
|
return this.client.collectors.run(name, args as never, this.client);
|
||||||
}
|
}
|
||||||
Event.fired = true;
|
Event.fired = true;
|
||||||
this.logger.debug(`executed a custom event [${name}]`, Event.data.once ? 'once' : '');
|
this.logger.debug(`executed a custom event [${name}]`, Event.data.once ? 'once' : '');
|
||||||
await Promise.all([Event.run(args, this.client), this.client.collectors.run(name, args as never)]);
|
await Promise.all([Event.run(args, this.client), this.client.collectors.run(name, args as never, this.client)]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await this.onFail(name, e);
|
await this.onFail(name, e);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user