feat: process worker messages in queue
This commit is contained in:
parent
2ea516e636
commit
6d8c0325e4
@ -1,17 +0,0 @@
|
|||||||
import { FeedCache } from "@snort/shared";
|
|
||||||
|
|
||||||
import { db, Payment } from "@/Db";
|
|
||||||
|
|
||||||
export class Payments extends FeedCache<Payment> {
|
|
||||||
constructor() {
|
|
||||||
super("PaymentsCache", db.payments);
|
|
||||||
}
|
|
||||||
|
|
||||||
key(of: Payment): string {
|
|
||||||
return of.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
takeSnapshot(): Array<Payment> {
|
|
||||||
return [...this.cache.values()];
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,6 @@ import { SnortSystemDb } from "@snort/system-web";
|
|||||||
|
|
||||||
import { ChatCache } from "./ChatCache";
|
import { ChatCache } from "./ChatCache";
|
||||||
import { GiftWrapCache } from "./GiftWrapCache";
|
import { GiftWrapCache } from "./GiftWrapCache";
|
||||||
import { Payments } from "./PaymentsCache";
|
|
||||||
|
|
||||||
export const SystemDb = new SnortSystemDb();
|
export const SystemDb = new SnortSystemDb();
|
||||||
export const UserCache = new UserProfileCache(SystemDb.users);
|
export const UserCache = new UserProfileCache(SystemDb.users);
|
||||||
@ -11,7 +10,6 @@ export const UserRelays = new UserRelaysCache(SystemDb.userRelays);
|
|||||||
export const RelayMetrics = new RelayMetricCache(SystemDb.relayMetrics);
|
export const RelayMetrics = new RelayMetricCache(SystemDb.relayMetrics);
|
||||||
|
|
||||||
export const Chats = new ChatCache();
|
export const Chats = new ChatCache();
|
||||||
export const PaymentsCache = new Payments();
|
|
||||||
export const GiftsCache = new GiftWrapCache();
|
export const GiftsCache = new GiftWrapCache();
|
||||||
|
|
||||||
export async function preload(follows?: Array<string>) {
|
export async function preload(follows?: Array<string>) {
|
||||||
|
@ -112,9 +112,6 @@ export default function useLoginFeed() {
|
|||||||
if (contactList) {
|
if (contactList) {
|
||||||
const pTags = contactList.tags.filter(a => a[0] === "p").map(a => a[1]);
|
const pTags = contactList.tags.filter(a => a[0] === "p").map(a => a[1]);
|
||||||
setFollows(login.id, pTags, contactList.created_at * 1000);
|
setFollows(login.id, pTags, contactList.created_at * 1000);
|
||||||
|
|
||||||
// TODO: fixup
|
|
||||||
// FollowsFeed.backFillIfMissing(system, pTags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const relays = getNewest(loginFeed.filter(a => a.kind === EventKind.Relays));
|
const relays = getNewest(loginFeed.filter(a => a.kind === EventKind.Relays));
|
||||||
|
@ -2,7 +2,7 @@ import { FeedCache } from "@snort/shared";
|
|||||||
import { ReactNode, useEffect, useState, useSyncExternalStore } from "react";
|
import { ReactNode, useEffect, useState, useSyncExternalStore } from "react";
|
||||||
import { FormattedMessage, FormattedNumber } from "react-intl";
|
import { FormattedMessage, FormattedNumber } from "react-intl";
|
||||||
|
|
||||||
import { Chats, GiftsCache, PaymentsCache, RelayMetrics, UserCache } from "@/Cache";
|
import { Chats, GiftsCache, RelayMetrics, UserCache } from "@/Cache";
|
||||||
import AsyncButton from "@/Components/Button/AsyncButton";
|
import AsyncButton from "@/Components/Button/AsyncButton";
|
||||||
import { Relay } from "@/system";
|
import { Relay } from "@/system";
|
||||||
|
|
||||||
@ -16,7 +16,6 @@ export function CacheSettings() {
|
|||||||
<CacheDetails cache={UserCache} name={<FormattedMessage defaultMessage="Profiles" id="2zJXeA" />} />
|
<CacheDetails cache={UserCache} name={<FormattedMessage defaultMessage="Profiles" id="2zJXeA" />} />
|
||||||
<CacheDetails cache={Chats} name={<FormattedMessage defaultMessage="Chats" id="ABAQyo" />} />
|
<CacheDetails cache={Chats} name={<FormattedMessage defaultMessage="Chats" id="ABAQyo" />} />
|
||||||
<CacheDetails cache={RelayMetrics} name={<FormattedMessage defaultMessage="Relay Metrics" id="tjpYlr" />} />
|
<CacheDetails cache={RelayMetrics} name={<FormattedMessage defaultMessage="Relay Metrics" id="tjpYlr" />} />
|
||||||
<CacheDetails cache={PaymentsCache} name={<FormattedMessage defaultMessage="Payments" id="iYc3Ld" />} />
|
|
||||||
<CacheDetails cache={GiftsCache} name={<FormattedMessage defaultMessage="Gift Wraps" id="fjAcWo" />} />
|
<CacheDetails cache={GiftsCache} name={<FormattedMessage defaultMessage="Gift Wraps" id="fjAcWo" />} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -61,25 +60,30 @@ function RelayCacheStats() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between br p bg-superdark">
|
<div className="flex justify-between br p bg-superdark">
|
||||||
<div className="flex flex-col g4">
|
<div className="flex flex-col g4 w-64">
|
||||||
<FormattedMessage defaultMessage="Worker Relay" id="xSoIUU" />
|
<FormattedMessage defaultMessage="Worker Relay" id="xSoIUU" />
|
||||||
{Object.entries(counts).map(([k, v]) => {
|
<table className="text-secondary">
|
||||||
return (
|
<thead>
|
||||||
<small key={k}>
|
<tr>
|
||||||
<FormattedMessage
|
<th className="text-left"><FormattedMessage defaultMessage="Kind" id="e5x8FT" /></th>
|
||||||
defaultMessage="{n} kind {k} events"
|
<th className="text-left"><FormattedMessage defaultMessage="Count" id="Aujn2T" /></th>
|
||||||
id="I97cCX"
|
</tr>
|
||||||
values={{
|
</thead>
|
||||||
n: <FormattedNumber value={v} />,
|
<tbody>
|
||||||
k: k,
|
{Object.entries(counts).sort(([, a], [, b]) => a > b ? -1 : 1).map(([k, v]) => {
|
||||||
}}
|
return (
|
||||||
/>
|
<tr key={k}>
|
||||||
</small>
|
<td>{k}</td>
|
||||||
);
|
<td><FormattedNumber value={v} /></td>
|
||||||
})}
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<AsyncButton onClick={() => {}}>
|
<AsyncButton onClick={() => { }}>
|
||||||
<FormattedMessage defaultMessage="Clear" id="/GCoTA" />
|
<FormattedMessage defaultMessage="Clear" id="/GCoTA" />
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import "./index.css";
|
import "./index.css";
|
||||||
import "@szhsin/react-menu/dist/index.css";
|
import "@szhsin/react-menu/dist/index.css";
|
||||||
import "@/assets/fonts/inter.css";
|
import "@/assets/fonts/inter.css";
|
||||||
import "./wdyr";
|
|
||||||
|
|
||||||
import { encodeTLVEntries } from "@snort/system";
|
import { encodeTLVEntries } from "@snort/system";
|
||||||
import { SnortContext } from "@snort/system-react";
|
import { SnortContext } from "@snort/system-react";
|
||||||
|
30
packages/worker-relay/src/queue.ts
Normal file
30
packages/worker-relay/src/queue.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export interface WorkQueueItem {
|
||||||
|
next: () => Promise<unknown>;
|
||||||
|
resolve(v: unknown): void;
|
||||||
|
reject(e: unknown): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function processWorkQueue(queue?: Array<WorkQueueItem>, queueDelay = 200) {
|
||||||
|
while (queue && queue.length > 0) {
|
||||||
|
const v = queue.shift();
|
||||||
|
if (v) {
|
||||||
|
try {
|
||||||
|
const ret = await v.next();
|
||||||
|
v.resolve(ret);
|
||||||
|
} catch (e) {
|
||||||
|
v.reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(() => processWorkQueue(queue, queueDelay), queueDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const barrierQueue = async <T>(queue: Array<WorkQueueItem>, then: () => Promise<T>): Promise<T> => {
|
||||||
|
return new Promise<T>((resolve, reject) => {
|
||||||
|
queue.push({
|
||||||
|
next: then,
|
||||||
|
resolve,
|
||||||
|
reject,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
@ -4,7 +4,7 @@ import { NostrEvent, ReqFilter, unixNowMs } from "./types";
|
|||||||
|
|
||||||
export class WorkerRelay {
|
export class WorkerRelay {
|
||||||
#sqlite?: Sqlite3Static;
|
#sqlite?: Sqlite3Static;
|
||||||
#log = (...msg: Array<any>) => console.debug(...msg);
|
#log = debug("WorkerRelay");
|
||||||
#db?: Database;
|
#db?: Database;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,7 +169,7 @@ export class WorkerRelay {
|
|||||||
* Get a summary about events table
|
* Get a summary about events table
|
||||||
*/
|
*/
|
||||||
summary() {
|
summary() {
|
||||||
const res = this.#db?.exec("select kind, count(*) from events group by kind order by 2 desc", {
|
const res = this.#db?.exec("select kind, count(*) from events group by kind", {
|
||||||
returnValue: "resultRows",
|
returnValue: "resultRows",
|
||||||
});
|
});
|
||||||
return Object.fromEntries(res?.map(a => [String(a[0]), a[1] as number]) ?? []);
|
return Object.fromEntries(res?.map(a => [String(a[0]), a[1] as number]) ?? []);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/// <reference lib="webworker" />
|
/// <reference lib="webworker" />
|
||||||
|
|
||||||
|
import { WorkQueueItem, barrierQueue, processWorkQueue } from "./queue";
|
||||||
import { WorkerRelay } from "./relay";
|
import { WorkerRelay } from "./relay";
|
||||||
import { NostrEvent, ReqCommand, ReqFilter, WorkerMessage } from "./types";
|
import { NostrEvent, ReqCommand, ReqFilter, WorkerMessage } from "./types";
|
||||||
|
|
||||||
@ -24,29 +25,38 @@ async function insertBatch() {
|
|||||||
}
|
}
|
||||||
setTimeout(() => insertBatch(), 100);
|
setTimeout(() => insertBatch(), 100);
|
||||||
|
|
||||||
|
let cmdQueue: Array<WorkQueueItem> = [];
|
||||||
|
processWorkQueue(cmdQueue, 50);
|
||||||
|
|
||||||
globalThis.onclose = () => {
|
globalThis.onclose = () => {
|
||||||
relay.close();
|
relay.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
globalThis.onmessage = async ev => {
|
globalThis.onmessage = ev => {
|
||||||
//console.debug(ev);
|
//console.debug(ev);
|
||||||
|
|
||||||
const msg = ev.data as WorkerMessage<any>;
|
const msg = ev.data as WorkerMessage<any>;
|
||||||
try {
|
try {
|
||||||
switch (msg.cmd) {
|
switch (msg.cmd) {
|
||||||
case "init": {
|
case "init": {
|
||||||
await relay.init();
|
barrierQueue(cmdQueue, async () => {
|
||||||
reply(msg.id, true);
|
await relay.init();
|
||||||
|
reply(msg.id, true);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "open": {
|
case "open": {
|
||||||
await relay.open("/relay.db");
|
barrierQueue(cmdQueue, async () => {
|
||||||
reply(msg.id, true);
|
await relay.open("/relay.db");
|
||||||
|
reply(msg.id, true);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "migrate": {
|
case "migrate": {
|
||||||
relay.migrate();
|
barrierQueue(cmdQueue, async () => {
|
||||||
reply(msg.id, true);
|
relay.migrate();
|
||||||
|
reply(msg.id, true);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "event": {
|
case "event": {
|
||||||
@ -55,27 +65,33 @@ globalThis.onmessage = async ev => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "req": {
|
case "req": {
|
||||||
const req = msg.args as ReqCommand;
|
barrierQueue(cmdQueue, async () => {
|
||||||
const results = [];
|
const req = msg.args as ReqCommand;
|
||||||
for (const r of req.slice(2)) {
|
const results = [];
|
||||||
results.push(...relay.req(r as ReqFilter));
|
for (const r of req.slice(2)) {
|
||||||
}
|
results.push(...relay.req(r as ReqFilter));
|
||||||
reply(msg.id, results);
|
}
|
||||||
|
reply(msg.id, results);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "count": {
|
case "count": {
|
||||||
const req = msg.args as ReqCommand;
|
barrierQueue(cmdQueue, async () => {
|
||||||
let results = 0;
|
const req = msg.args as ReqCommand;
|
||||||
for (const r of req.slice(2)) {
|
let results = 0;
|
||||||
const c = relay.count(r as ReqFilter);
|
for (const r of req.slice(2)) {
|
||||||
results += c;
|
const c = relay.count(r as ReqFilter);
|
||||||
}
|
results += c;
|
||||||
reply(msg.id, results);
|
}
|
||||||
|
reply(msg.id, results);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "summary": {
|
case "summary": {
|
||||||
const res = relay.summary();
|
barrierQueue(cmdQueue, async () => {
|
||||||
reply(msg.id, res);
|
const res = relay.summary();
|
||||||
|
reply(msg.id, res);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
Loading…
Reference in New Issue
Block a user