aboutsummaryrefslogtreecommitdiffstats
path: root/lib/nostr.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2022-12-29 16:07:13 -0800
committerAdam Soltys <[email protected]>2022-12-29 16:07:13 -0800
commit0f20d1cb0ca5a65ff6ae5fc4bb97657fc7ba4ee5 (patch)
tree4292426bcf7337e6f2b22f1dc4113e7a3f32716c /lib/nostr.js
parent33bfa7d2d4d74f4724d117ad58a825253e53d321 (diff)
downloadcoinos-server-0f20d1cb0ca5a65ff6ae5fc4bb97657fc7ba4ee5.tar.gz
coinos-server-0f20d1cb0ca5a65ff6ae5fc4bb97657fc7ba4ee5.zip
follower query caching
Diffstat (limited to 'lib/nostr.js')
-rw-r--r--lib/nostr.js120
1 files changed, 65 insertions, 55 deletions
diff --git a/lib/nostr.js b/lib/nostr.js
index 034a4aaa..dc400b7f 100644
--- a/lib/nostr.js
+++ b/lib/nostr.js
@@ -14,15 +14,58 @@ pool.on("open", relay => {
});
export let coinos;
+let now = () => Math.round(Date.now() / 1000);
+
+let timeouts = {};
+export let q = async (sub, query, timeout = 8000) =>
+ new Promise(async (r, j) => {
+ let rejected;
+ if (!coinos) return j(new Error("relay not initialized"));
+ query.since = await redis.get(`since:${sub}`);
+ if (now() - query.since < 3600) return r();
+
+ coinos.on("eose", s => !rejected && s === sub && r(timeouts[sub].clear()));
+
+ coinos.subscribe(sub, query);
+
+ timeouts[sub] = {
+ async clear() {
+ clearTimeout(this.timer);
+ delete timeouts[sub];
+ coinos.unsubscribe(sub);
+ await redis.set(`since:${sub}`, now());
+ },
+ extend(t = timeout) {
+ clearTimeout(this.timer);
+ this.timer = setTimeout(() => {
+ j(new Error(`query timed out: ${sub} ${Date.now()}`));
+ coinos.unsubscribe(sub);
+ rejected = true;
+ }, t);
+ },
+ timer: undefined
+ };
+
+ timeouts[sub].extend(timeout);
+ });
+
let seen = [];
-let timeout;
+
+let getUser = async pubkey =>
+ JSON.parse(await redis.get(`user:${pubkey}`)) || {
+ username: pubkey.substr(0, 6),
+ pubkey,
+ anon: true
+ };
+
pool.on("event", async (relay, sub, ev) => {
+ if (timeouts[sub]) timeouts[sub].extend();
try {
- let parsed;
+ let content;
try {
- parsed = JSON.parse(ev.content);
+ content = JSON.parse(ev.content);
} catch (e) {
- parsed = ev.content;
+ content = ev.content;
}
if (sub === "live") {
@@ -38,48 +81,25 @@ pool.on("event", async (relay, sub, ev) => {
if (coinos && ev.kind < 5) {
coinos.send(["EVENT", ev]);
- let newuser = {
- username: pubkey.substr(0, 6),
- pubkey,
- anon: true,
- follows: [],
- followers: []
- };
-
- ev.user = JSON.parse(await redis.get(`user:${pubkey}`)) || newuser;
-
- relay.subscribe("zero", {
- limit: 1,
- kinds: [0],
- authors: [pubkey]
- });
+ ev.user = await getUser(pubkey);
broadcast("event", ev);
}
- } else if (sub === "zero") {
+ } else if (sub.includes("profile")) {
let { pubkey } = ev;
- let newuser = {
- username: pubkey.substr(0, 6),
- pubkey,
- anon: true,
- follows: [],
- followers: []
- };
+ let user = await getUser(pubkey);
- let user = JSON.parse(await redis.get(`user:${pubkey}`)) || newuser;
+ if (user.updated > ev.created_at) return;
- if (user.profileUpdated > ev.created_at) return;
+ if (content.name && user.username === pubkey.substr(0, 6))
+ user.username = content.name;
- if (parsed.name && user.username === pubkey.substr(0, 6))
- user.username = parsed.name;
-
- delete parsed.name;
+ delete content.name;
user = {
...user,
- ...parsed,
- initialized: true,
- profileUpdated: ev.created_at
+ ...content,
+ updated: ev.created_at
};
await redis.set(`user:${pubkey}`, JSON.stringify(user));
@@ -89,39 +109,29 @@ pool.on("event", async (relay, sub, ev) => {
await redis.set(`${pubkey}:follows`, JSON.stringify(ev.tags));
for (let f of ev.tags) {
let [_, followPubkey] = f;
- pool.subscribe("zero", {
- limit: 1,
- kinds: [0],
- authors: [followPubkey]
- });
await redis.sAdd(`${followPubkey}:followers`, pubkey);
}
- store.fetching[pubkey] = false;
} else if (sub.includes("followers")) {
let followed = sub.split(":")[0];
let { pubkey } = ev;
await redis.sAdd(`${followed}:followers`, pubkey);
- store.fetching[pubkey] = false;
} else {
if (!relay.url.includes("coinos")) return;
let pubkey = sub;
- clearTimeout(store.timeouts[pubkey]);
+ ev.user = await getUser(pubkey);
- ev.user = JSON.parse(await redis.get(`user:${pubkey}`)) || {
- username: pubkey.substr(0, 6),
- pubkey,
- anon: true
- };
+ // console.log(ev.user.username, "UPDATED AT", ev.user.updated)
+ if (!ev.user.updated) {
+ relay.subscribe(`${pubkey}:${ev.id}:profile`, {
+ limit: 1,
+ kinds: [0],
+ authors: [pubkey]
+ });
+ }
await redis.sAdd(pubkey, ev.id);
await redis.set(`ev:${ev.id}`, JSON.stringify(ev));
-
- store.fetching[pubkey] = true;
- store.timeouts[pubkey] = setTimeout(
- () => (store.fetching[pubkey] = false),
- 100
- );
}
} catch (e) {
console.log(e);