refactor: events to a pure stream instead of being part of topics
NOTE: tests are passing, but the client is broken
This commit is contained in:
parent
c34069066d
commit
a5707e2f81
31 changed files with 934 additions and 686 deletions
153
models/event.ts
153
models/event.ts
|
|
@ -1,4 +1,4 @@
|
|||
import { by_character, by_lurid } from '@andyburke/fsdb/organizers';
|
||||
import { by_lurid } from '@andyburke/fsdb/organizers';
|
||||
import { FSDB_COLLECTION } from '@andyburke/fsdb';
|
||||
import { FSDB_INDEXER_SYMLINKS } from '@andyburke/fsdb/indexers';
|
||||
import { EMOJIS } from '../public/js/emojis/en.ts';
|
||||
|
|
@ -16,7 +16,9 @@ import { EMOJIS } from '../public/js/emojis/en.ts';
|
|||
* @property {string} creator_id - id of the source user
|
||||
* @property {string} type - event type
|
||||
* @property {string} [parent_id] - optional parent event id
|
||||
* @property {string[]} [tags] - optional event tags
|
||||
* @property {string} [channel] - optional channel
|
||||
* @property {string} [topic] - optional topic
|
||||
* @property {string[]} [tags] - optional tags
|
||||
* @property {Record<string,any>} [data] - optional data payload of the event
|
||||
* @property {TIMESTAMPS} timestamps - timestamps that will be set by the server
|
||||
*/
|
||||
|
|
@ -25,6 +27,8 @@ export type EVENT = {
|
|||
creator_id: string;
|
||||
type: string;
|
||||
parent_id?: string;
|
||||
channel?: string;
|
||||
topic?: string;
|
||||
tags?: string[];
|
||||
data?: Record<string, any>;
|
||||
timestamps: {
|
||||
|
|
@ -33,11 +37,6 @@ export type EVENT = {
|
|||
};
|
||||
};
|
||||
|
||||
type TOPIC_EVENT_CACHE_ENTRY = {
|
||||
collection: FSDB_COLLECTION<EVENT>;
|
||||
eviction_timeout: number;
|
||||
};
|
||||
|
||||
// TODO: separate out these different validators somewhere?
|
||||
export function VALIDATE_EVENT(event: EVENT) {
|
||||
const errors: any[] = [];
|
||||
|
|
@ -111,6 +110,8 @@ export function VALIDATE_EVENT(event: EVENT) {
|
|||
});
|
||||
}
|
||||
break;
|
||||
case 'presence':
|
||||
break;
|
||||
case 'reaction':
|
||||
if (typeof event.parent_id !== 'string') {
|
||||
errors.push({
|
||||
|
|
@ -148,78 +149,76 @@ export function VALIDATE_EVENT(event: EVENT) {
|
|||
return errors.length ? errors : undefined;
|
||||
}
|
||||
|
||||
const TOPIC_EVENT_ID_MATCHER = /^(?<event_type>.*):(?<event_id>.*)$/;
|
||||
const EVENT_ID_EXTRACTOR = /^(?<event_type>.*):(?<event_id>.*)$/;
|
||||
|
||||
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] ?? {
|
||||
collection: new FSDB_COLLECTION<EVENT>({
|
||||
name: `topics/${topic_id.slice(0, 14)}/${topic_id.slice(0, 34)}/${topic_id}/events`,
|
||||
id_field: 'id',
|
||||
organize: (id) => {
|
||||
TOPIC_EVENT_ID_MATCHER.lastIndex = 0;
|
||||
|
||||
const groups: Record<string, string> | undefined = TOPIC_EVENT_ID_MATCHER.exec(id ?? '')?.groups;
|
||||
|
||||
if (!groups) {
|
||||
throw new Error('Could not parse event id: ' + id);
|
||||
}
|
||||
|
||||
const event_type = groups.event_type;
|
||||
const event_id = groups.event_id;
|
||||
|
||||
return [
|
||||
event_type,
|
||||
event_id.slice(0, 14),
|
||||
event_id.slice(0, 34),
|
||||
event_id,
|
||||
`${event_id}.json` /* TODO: this should be ${id}.json - need to write a converter */
|
||||
];
|
||||
},
|
||||
indexers: {
|
||||
creator_id: new FSDB_INDEXER_SYMLINKS<EVENT>({
|
||||
name: 'creator_id',
|
||||
field: 'creator_id',
|
||||
to_many: true,
|
||||
organize: by_lurid
|
||||
}),
|
||||
|
||||
parent_id: new FSDB_INDEXER_SYMLINKS<EVENT>({
|
||||
name: 'parent_id',
|
||||
field: 'parent_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
|
||||
})
|
||||
}
|
||||
}),
|
||||
eviction_timeout: 0
|
||||
};
|
||||
|
||||
if (TOPIC_EVENTS[topic_id].eviction_timeout) {
|
||||
clearTimeout(TOPIC_EVENTS[topic_id].eviction_timeout);
|
||||
}
|
||||
|
||||
TOPIC_EVENTS[topic_id].eviction_timeout = setTimeout(() => {
|
||||
delete TOPIC_EVENTS[topic_id];
|
||||
}, 60_000 * 5);
|
||||
|
||||
return TOPIC_EVENTS[topic_id].collection;
|
||||
function smart_event_id_organizer(id: string) {
|
||||
const [event_type, event_id] = id.split(':', 2);
|
||||
const event_dirs = by_lurid(event_id).slice(0, -1);
|
||||
return [event_type, ...event_dirs, `${id}.json`];
|
||||
}
|
||||
|
||||
export function clear_topic_events_cache() {
|
||||
for (const [topic_id, cached] of Object.entries(TOPIC_EVENTS)) {
|
||||
if (cached.eviction_timeout) {
|
||||
clearTimeout(cached.eviction_timeout);
|
||||
export const EVENTS = new FSDB_COLLECTION<EVENT>({
|
||||
name: `events`,
|
||||
id_field: 'id',
|
||||
organize: (id) => {
|
||||
EVENT_ID_EXTRACTOR.lastIndex = 0;
|
||||
|
||||
const groups: Record<string, string> | undefined = EVENT_ID_EXTRACTOR.exec(id ?? '')?.groups;
|
||||
|
||||
if (!groups) {
|
||||
throw new Error('Could not parse event id: ' + id);
|
||||
}
|
||||
delete TOPIC_EVENTS[topic_id];
|
||||
|
||||
const event_type = groups.event_type;
|
||||
const event_id = groups.event_id;
|
||||
|
||||
return [
|
||||
event_type,
|
||||
event_id.slice(0, 14),
|
||||
event_id.slice(0, 34),
|
||||
event_id,
|
||||
`${id}.json`
|
||||
];
|
||||
},
|
||||
indexers: {
|
||||
creator_id: new FSDB_INDEXER_SYMLINKS<EVENT>({
|
||||
name: 'creator_id',
|
||||
field: 'creator_id',
|
||||
to_many: true,
|
||||
organize: by_lurid
|
||||
}),
|
||||
|
||||
parent_id: new FSDB_INDEXER_SYMLINKS<EVENT>({
|
||||
name: 'parent_id',
|
||||
field: 'parent_id',
|
||||
to_many: true,
|
||||
organize: smart_event_id_organizer
|
||||
}),
|
||||
|
||||
channel: new FSDB_INDEXER_SYMLINKS<EVENT>({
|
||||
name: 'channel',
|
||||
field: 'channel',
|
||||
to_many: true,
|
||||
organize: (channel: string) => [channel],
|
||||
organize_id: smart_event_id_organizer
|
||||
}),
|
||||
|
||||
topic: new FSDB_INDEXER_SYMLINKS<EVENT>({
|
||||
name: 'topic',
|
||||
field: 'topic',
|
||||
to_many: true,
|
||||
organize: (topic: string) => [topic],
|
||||
organize_id: smart_event_id_organizer
|
||||
}),
|
||||
|
||||
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: (tag: string) => tag.length > 3 ? [tag.substring(0, 3), tag] : [tag],
|
||||
organize_id: smart_event_id_organizer
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue