@evanp/activitypub-bot 0.45.12 → 0.45.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,12 @@ and this project adheres to
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.45.13] - 2026-05-10
13
+
14
+ ### Changed
15
+
16
+ - Replace in-memory ObjectCache with persistent and shared RemoteObjectCache.
17
+
12
18
  ## [0.45.12] - 2026-05-09
13
19
 
14
20
  ### Changed
@@ -47,6 +47,12 @@ export class ActivityHandler {
47
47
  'activity parameter must be an object'
48
48
  )
49
49
 
50
+ await this.#cache.set(
51
+ activity.id,
52
+ bot.username,
53
+ await activity.export({ useOriginalContext: true })
54
+ )
55
+
50
56
  let handled = false
51
57
 
52
58
  try {
@@ -96,9 +102,11 @@ export class ActivityHandler {
96
102
  return
97
103
  }
98
104
  if (await this.#authz.sameOrigin(activity, object)) {
99
- await this.#cache.save(object)
100
- } else {
101
- await this.#cache.saveReceived(object)
105
+ await this.#cache.set(
106
+ object.id,
107
+ bot.username,
108
+ await object.export({ useOriginalContext: true })
109
+ )
102
110
  }
103
111
  await this.#handleCreateReplies(bot, activity, actor, object)
104
112
  await this.#handleCreateThread(bot, activity, actor, object)
@@ -183,6 +191,7 @@ export class ActivityHandler {
183
191
  'Not a local thread',
184
192
  { thread: thread.id }
185
193
  )
194
+ await this.#cache.clear(thread.id)
186
195
  return
187
196
  }
188
197
  const root = await this.#threadRoot(thread)
@@ -231,52 +240,22 @@ export class ActivityHandler {
231
240
 
232
241
  async #handleUpdate (bot, activity) {
233
242
  const object = this.#getObject(activity)
234
- if (await this.#authz.sameOrigin(activity, object)) {
235
- await this.#cache.save(object)
236
- } else {
237
- await this.#cache.saveReceived(object)
238
- }
243
+ await this.#cache.clear(object.id)
239
244
  }
240
245
 
241
246
  async #handleDelete (bot, activity) {
242
247
  const object = this.#getObject(activity)
243
- await this.#cache.clear(object)
248
+ await this.#cache.clear(object.id)
244
249
  }
245
250
 
246
251
  async #handleAdd (bot, activity) {
247
- const actor = this.#getActor(activity)
248
252
  const target = this.#getTarget(activity)
249
- const object = this.#getObject(activity)
250
- if (await this.#authz.sameOrigin(actor, object)) {
251
- await this.#cache.save(object)
252
- } else {
253
- await this.#cache.saveReceived(object)
254
- }
255
- if (await this.#authz.sameOrigin(actor, target)) {
256
- await this.#cache.save(target)
257
- await this.#cache.saveMembership(target, object)
258
- } else {
259
- await this.#cache.saveReceived(target)
260
- await this.#cache.saveMembershipReceived(target, object)
261
- }
253
+ await this.#cache.clear(target.id)
262
254
  }
263
255
 
264
256
  async #handleRemove (bot, activity) {
265
- const actor = this.#getActor(activity)
266
257
  const target = this.#getTarget(activity)
267
- const object = this.#getObject(activity)
268
- if (await this.#authz.sameOrigin(actor, object)) {
269
- await this.#cache.save(object)
270
- } else {
271
- await this.#cache.saveReceived(object)
272
- }
273
- if (await this.#authz.sameOrigin(actor, target)) {
274
- await this.#cache.save(target)
275
- await this.#cache.saveMembership(target, object, false)
276
- } else {
277
- await this.#cache.saveReceived(target)
278
- await this.#cache.saveMembershipReceived(target, object, false)
279
- }
258
+ await this.#cache.clear(target.id)
280
259
  }
281
260
 
282
261
  async #handleFollow (bot, activity) {
@@ -993,7 +972,7 @@ export class ActivityHandler {
993
972
  // Check it from cache
994
973
  const id = object.id
995
974
  this.#logger.debug({ msg: 'Checking cache', object: id })
996
- object = await this.#cache.get(id)
975
+ object = await as2.import((await this.#cache.get(id, bot.username)).object)
997
976
  if (object &&
998
977
  (!required.includes('type') || object.type) &&
999
978
  !others.find((prop) => !object.has(prop))) {
@@ -1004,7 +983,11 @@ export class ActivityHandler {
1004
983
  this.#logger.debug({ msg: 'Checking remote', object: id })
1005
984
  object = await this.#client.get(id, bot.username)
1006
985
  this.#logger.debug({ msg: 'Object fetched from remote', object: object.id, objectText: await object.write() })
1007
- this.#cache.save(object)
986
+ await this.#cache.set(
987
+ object.id,
988
+ bot.username,
989
+ await object.export({ useOriginalContext: true })
990
+ )
1008
991
  if (object &&
1009
992
  (!required.includes('type') || object.type) &&
1010
993
  !others.find((prop) => !object.has(prop))) {
package/lib/app.js CHANGED
@@ -23,7 +23,6 @@ import { HTTPSignature } from './httpsignature.js'
23
23
  import { Authorizer } from './authorizer.js'
24
24
  import { RemoteKeyStorage } from './remotekeystorage.js'
25
25
  import { ActivityHandler } from './activityhandler.js'
26
- import { ObjectCache } from '../lib/objectcache.js'
27
26
  import serverRouter from './routes/server.js'
28
27
  import userRouter from './routes/user.js'
29
28
  import objectRouter from './routes/object.js'
@@ -116,17 +115,12 @@ export async function makeApp ({ databaseUrl, origin, bots, logLevel = 'silent',
116
115
  endpointCache
117
116
  )
118
117
  const authorizer = new Authorizer(actorStorage, formatter, client)
119
- const cache = new ObjectCache({
120
- longTTL: 3600 * 1000,
121
- shortTTL: 300 * 1000,
122
- maxItems: 1000
123
- })
124
118
  const activityHandler = new ActivityHandler(
125
119
  actorStorage,
126
120
  objectStorage,
127
121
  distributor,
128
122
  formatter,
129
- cache,
123
+ remoteObjectCache,
130
124
  authorizer,
131
125
  logger,
132
126
  client
@@ -59,7 +59,7 @@ export class RemoteObjectCache {
59
59
  return result
60
60
  }
61
61
 
62
- async set (id, username, object, headers) {
62
+ async set (id, username, object, headers = new Headers()) {
63
63
  assert.ok(id)
64
64
  assert.strictEqual(typeof id, 'string')
65
65
  assert.ok(username)
@@ -95,6 +95,14 @@ export class RemoteObjectCache {
95
95
  )
96
96
  }
97
97
 
98
+ async clear (id) {
99
+ await this.#connection.query(
100
+ `DELETE FROM remote_object_cache
101
+ WHERE id = ?`,
102
+ { replacements: [id] }
103
+ )
104
+ }
105
+
98
106
  async #getExpiry (object, headers) {
99
107
  assert.ok(object)
100
108
  assert.strictEqual(typeof object, 'object')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evanp/activitypub-bot",
3
- "version": "0.45.12",
3
+ "version": "0.45.13",
4
4
  "description": "server-side ActivityPub bot framework",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -1,51 +0,0 @@
1
- import * as ttlcachePkg from '@isaacs/ttlcache'
2
-
3
- const TTLCache =
4
- ttlcachePkg.TTLCache ?? ttlcachePkg.default ?? ttlcachePkg
5
-
6
- export class ObjectCache {
7
- #objects = null
8
- #members = null
9
- constructor ({ longTTL, shortTTL, maxItems }) {
10
- this.#objects = new TTLCache({ ttl: shortTTL, max: maxItems })
11
- this.#members = new TTLCache({ ttl: shortTTL, max: maxItems })
12
- this.longTTL = longTTL
13
- this.shortTTL = shortTTL
14
- this.maxItems = maxItems
15
- }
16
-
17
- async initialize () {
18
- }
19
-
20
- async get (id) {
21
- return this.#objects.get(id)
22
- }
23
-
24
- async save (object) {
25
- return this.#objects.set(object.id, object, { ttl: this.longTTL })
26
- }
27
-
28
- async saveReceived (object) {
29
- return this.#objects.set(object.id, object, { ttl: this.shortTTL })
30
- }
31
-
32
- async clear (object) {
33
- return this.#objects.delete(object.id)
34
- }
35
-
36
- membershipKey (collection, object) {
37
- return `${collection.id}:${object.id}`
38
- }
39
-
40
- async saveMembership (collection, object, isMember = true) {
41
- return this.#members.set(this.membershipKey(collection, object), isMember, { ttl: this.longTTL })
42
- }
43
-
44
- async saveMembershipReceived (collection, object, isMember = true) {
45
- return this.#members.set(this.membershipKey(collection, object), isMember, { ttl: this.shortTTL })
46
- }
47
-
48
- async isMember (collection, object) {
49
- return this.#members.get(this.membershipKey(collection, object))
50
- }
51
- }