autonomous.contact/models/event.ts

108 lines
2.8 KiB
TypeScript
Raw Normal View History

import { by_character, by_lurid } from '@andyburke/fsdb/organizers';
import { FSDB_COLLECTION } from '@andyburke/fsdb';
import { FSDB_INDEXER_SYMLINKS } from '@andyburke/fsdb/indexers';
/**
* @typedef {object} TIMESTAMPS
* @property {string} created when the event was created
* @property {string} updated when the event was last updated
*/
/**
* Event
*
2025-07-02 21:28:07 -07:00
* @property {string} id - lurid
* @property {string} creator_id - id of the source user
* @property {string} type - event type
2025-09-09 15:32:07 -07:00
* @property {string} [parent_id] - optional parent event id
* @property {string[]} [tags] - optional event tags
* @property {Record<string,any>} [data] - optional data payload of the event
* @property {TIMESTAMPS} timestamps - timestamps that will be set by the server
*/
export type EVENT = {
id: string;
creator_id: string;
type: string;
2025-09-09 15:32:07 -07:00
parent_id?: string;
tags?: string[];
data?: Record<string, any>;
timestamps: {
created: string;
updated: string;
};
};
2025-09-10 12:51:27 -07:00
type TOPIC_EVENT_CACHE_ENTRY = {
2025-07-02 21:28:07 -07:00
collection: FSDB_COLLECTION<EVENT>;
eviction_timeout: number;
};
const TOPIC_EVENT_ID_MATCHER = /^(?<event_type>.*):(?<event_id>.*)$/;
2025-09-10 12:51:27 -07:00
const TOPIC_EVENTS: Record<string, TOPIC_EVENT_CACHE_ENTRY> = {};
export function get_events_collection_for_topic(topic_id: string): FSDB_COLLECTION<EVENT> {
TOPIC_EVENTS[topic_id] = TOPIC_EVENTS[topic_id] ?? {
2025-07-02 21:28:07 -07:00
collection: new FSDB_COLLECTION<EVENT>({
2025-09-10 12:51:27 -07:00
name: `topics/${topic_id.slice(0, 14)}/${topic_id.slice(0, 34)}/${topic_id}/events`,
2025-07-02 21:28:07 -07:00
id_field: 'id',
organize: (id) => {
TOPIC_EVENT_ID_MATCHER.lastIndex = 0;
const {
groups: {
event_type,
event_id
}
} = TOPIC_EVENT_ID_MATCHER.exec(id ?? '') ?? {
groups: {}
};
return [
event_type,
event_id.slice(0, 14),
event_id.slice(0, 34),
event_id,
`${event_id}.json`
];
},
2025-07-02 21:28:07 -07:00
indexers: {
creator_id: new FSDB_INDEXER_SYMLINKS<EVENT>({
name: 'creator_id',
field: 'creator_id',
to_many: true,
organize: by_lurid
}),
tags: new FSDB_INDEXER_SYMLINKS<EVENT>({
name: 'tags',
get_values_to_index: (event: EVENT): string[] => {
return (event.tags ?? []).map((tag: string) => tag.toLowerCase());
},
to_many: true,
organize: by_character
})
}
}),
2025-07-02 21:28:07 -07:00
eviction_timeout: 0
};
2025-09-10 12:51:27 -07:00
if (TOPIC_EVENTS[topic_id].eviction_timeout) {
clearTimeout(TOPIC_EVENTS[topic_id].eviction_timeout);
2025-07-02 21:28:07 -07:00
}
2025-09-10 12:51:27 -07:00
TOPIC_EVENTS[topic_id].eviction_timeout = setTimeout(() => {
delete TOPIC_EVENTS[topic_id];
2025-07-02 21:28:07 -07:00
}, 60_000 * 5);
2025-09-10 12:51:27 -07:00
return TOPIC_EVENTS[topic_id].collection;
2025-07-02 21:28:07 -07:00
}
2025-09-10 12:51:27 -07:00
export function clear_topic_events_cache() {
for (const [topic_id, cached] of Object.entries(TOPIC_EVENTS)) {
2025-07-02 21:28:07 -07:00
if (cached.eviction_timeout) {
clearTimeout(cached.eviction_timeout);
}
2025-09-10 12:51:27 -07:00
delete TOPIC_EVENTS[topic_id];
}
2025-07-02 21:28:07 -07:00
}