@apibara/plugin-mongo 2.0.0-beta.42 → 2.1.0-beta.10

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/dist/index.cjs CHANGED
@@ -39,6 +39,29 @@ async function finalize(db, session, cursor, collections) {
39
39
  );
40
40
  }
41
41
  }
42
+ async function cleanupStorage(db, session, collections) {
43
+ for (const collection of collections) {
44
+ try {
45
+ await db.collection(collection).deleteMany({}, { session });
46
+ } catch (error) {
47
+ throw new Error(`Failed to clean up collection ${collection}: ${error}`);
48
+ }
49
+ }
50
+ }
51
+
52
+ class MongoStorageError extends Error {
53
+ constructor(message, options) {
54
+ super(message, options);
55
+ this.name = "MongoStorageError";
56
+ }
57
+ }
58
+ async function withTransaction(client, cb) {
59
+ return await client.withSession(async (session) => {
60
+ return await session.withTransaction(async (session2) => {
61
+ return await cb(session2);
62
+ });
63
+ });
64
+ }
42
65
 
43
66
  const checkpointCollectionName = "checkpoints";
44
67
  const filterCollectionName = "filters";
@@ -134,6 +157,17 @@ async function finalizeState(props) {
134
157
  { session }
135
158
  );
136
159
  }
160
+ async function resetPersistence(props) {
161
+ const { db, session, indexerId } = props;
162
+ try {
163
+ await db.collection(checkpointCollectionName).deleteMany({ id: indexerId }, { session });
164
+ await db.collection(filterCollectionName).deleteMany({ id: indexerId }, { session });
165
+ } catch (error) {
166
+ throw new MongoStorageError("Failed to reset persistence state", {
167
+ cause: error
168
+ });
169
+ }
170
+ }
137
171
 
138
172
  class MongoStorage {
139
173
  constructor(db, session, endCursor) {
@@ -305,20 +339,6 @@ class MongoCollection {
305
339
  }
306
340
  }
307
341
 
308
- class MongoStorageError extends Error {
309
- constructor(message) {
310
- super(message);
311
- this.name = "MongoStorageError";
312
- }
313
- }
314
- async function withTransaction(client, cb) {
315
- return await client.withSession(async (session) => {
316
- return await session.withTransaction(async (session2) => {
317
- return await cb(session2);
318
- });
319
- });
320
- }
321
-
322
342
  const MONGO_PROPERTY = "_mongo";
323
343
  function useMongoStorage() {
324
344
  const context = indexer.useIndexerContext();
@@ -339,9 +359,24 @@ function mongoStorage({
339
359
  }) {
340
360
  return plugins.defineIndexerPlugin((indexer) => {
341
361
  let indexerId = "";
362
+ const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true";
342
363
  indexer.hooks.hook("run:before", async () => {
343
364
  const { indexerName } = plugins$1.useInternalContext();
344
365
  indexerId = internal.generateIndexerId(indexerName, identifier);
366
+ const logger = plugins.useLogger();
367
+ if (alwaysReindex) {
368
+ logger.warn(
369
+ `Reindexing: Deleting all data from collections - ${collections.join(", ")}`
370
+ );
371
+ await withTransaction(client, async (session) => {
372
+ const db = client.db(dbName, dbOptions);
373
+ await cleanupStorage(db, session, collections);
374
+ if (enablePersistence) {
375
+ await resetPersistence({ db, session, indexerId });
376
+ }
377
+ logger.success("All data has been cleaned up for reindexing");
378
+ });
379
+ }
345
380
  await withTransaction(client, async (session) => {
346
381
  const db = client.db(dbName, dbOptions);
347
382
  if (enablePersistence) {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { useIndexerContext } from '@apibara/indexer';
2
- import { defineIndexerPlugin } from '@apibara/indexer/plugins';
2
+ import { defineIndexerPlugin, useLogger } from '@apibara/indexer/plugins';
3
3
  import { generateIndexerId } from '@apibara/indexer/internal';
4
4
  import { useInternalContext } from '@apibara/indexer/internal/plugins';
5
5
  import { normalizeCursor } from '@apibara/protocol';
@@ -37,6 +37,29 @@ async function finalize(db, session, cursor, collections) {
37
37
  );
38
38
  }
39
39
  }
40
+ async function cleanupStorage(db, session, collections) {
41
+ for (const collection of collections) {
42
+ try {
43
+ await db.collection(collection).deleteMany({}, { session });
44
+ } catch (error) {
45
+ throw new Error(`Failed to clean up collection ${collection}: ${error}`);
46
+ }
47
+ }
48
+ }
49
+
50
+ class MongoStorageError extends Error {
51
+ constructor(message, options) {
52
+ super(message, options);
53
+ this.name = "MongoStorageError";
54
+ }
55
+ }
56
+ async function withTransaction(client, cb) {
57
+ return await client.withSession(async (session) => {
58
+ return await session.withTransaction(async (session2) => {
59
+ return await cb(session2);
60
+ });
61
+ });
62
+ }
40
63
 
41
64
  const checkpointCollectionName = "checkpoints";
42
65
  const filterCollectionName = "filters";
@@ -132,6 +155,17 @@ async function finalizeState(props) {
132
155
  { session }
133
156
  );
134
157
  }
158
+ async function resetPersistence(props) {
159
+ const { db, session, indexerId } = props;
160
+ try {
161
+ await db.collection(checkpointCollectionName).deleteMany({ id: indexerId }, { session });
162
+ await db.collection(filterCollectionName).deleteMany({ id: indexerId }, { session });
163
+ } catch (error) {
164
+ throw new MongoStorageError("Failed to reset persistence state", {
165
+ cause: error
166
+ });
167
+ }
168
+ }
135
169
 
136
170
  class MongoStorage {
137
171
  constructor(db, session, endCursor) {
@@ -303,20 +337,6 @@ class MongoCollection {
303
337
  }
304
338
  }
305
339
 
306
- class MongoStorageError extends Error {
307
- constructor(message) {
308
- super(message);
309
- this.name = "MongoStorageError";
310
- }
311
- }
312
- async function withTransaction(client, cb) {
313
- return await client.withSession(async (session) => {
314
- return await session.withTransaction(async (session2) => {
315
- return await cb(session2);
316
- });
317
- });
318
- }
319
-
320
340
  const MONGO_PROPERTY = "_mongo";
321
341
  function useMongoStorage() {
322
342
  const context = useIndexerContext();
@@ -337,9 +357,24 @@ function mongoStorage({
337
357
  }) {
338
358
  return defineIndexerPlugin((indexer) => {
339
359
  let indexerId = "";
360
+ const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true";
340
361
  indexer.hooks.hook("run:before", async () => {
341
362
  const { indexerName } = useInternalContext();
342
363
  indexerId = generateIndexerId(indexerName, identifier);
364
+ const logger = useLogger();
365
+ if (alwaysReindex) {
366
+ logger.warn(
367
+ `Reindexing: Deleting all data from collections - ${collections.join(", ")}`
368
+ );
369
+ await withTransaction(client, async (session) => {
370
+ const db = client.db(dbName, dbOptions);
371
+ await cleanupStorage(db, session, collections);
372
+ if (enablePersistence) {
373
+ await resetPersistence({ db, session, indexerId });
374
+ }
375
+ logger.success("All data has been cleaned up for reindexing");
376
+ });
377
+ }
343
378
  await withTransaction(client, async (session) => {
344
379
  const db = client.db(dbName, dbOptions);
345
380
  if (enablePersistence) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apibara/plugin-mongo",
3
- "version": "2.0.0-beta.42",
3
+ "version": "2.1.0-beta.10",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -35,7 +35,7 @@
35
35
  "mongodb": "^6.12.0"
36
36
  },
37
37
  "dependencies": {
38
- "@apibara/indexer": "2.0.0-beta.42",
39
- "@apibara/protocol": "2.0.0-beta.42"
38
+ "@apibara/indexer": "2.1.0-beta.10",
39
+ "@apibara/protocol": "2.1.0-beta.10"
40
40
  }
41
41
  }
package/src/index.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  import { useIndexerContext } from "@apibara/indexer";
2
- import { defineIndexerPlugin } from "@apibara/indexer/plugins";
2
+ import { defineIndexerPlugin, useLogger } from "@apibara/indexer/plugins";
3
3
  import type { DbOptions, MongoClient } from "mongodb";
4
4
 
5
5
  import { generateIndexerId } from "@apibara/indexer/internal";
6
6
  import { useInternalContext } from "@apibara/indexer/internal/plugins";
7
- import { finalize, invalidate } from "./mongo";
7
+ import { cleanupStorage, finalize, invalidate } from "./mongo";
8
8
  import {
9
9
  finalizeState,
10
10
  getState,
11
11
  initializePersistentState,
12
12
  invalidateState,
13
13
  persistState,
14
+ resetPersistence,
14
15
  } from "./persistence";
15
16
  import { MongoStorage } from "./storage";
16
17
  import { MongoStorageError, withTransaction } from "./utils";
@@ -60,10 +61,30 @@ export function mongoStorage<TFilter, TBlock>({
60
61
  }: MongoStorageOptions) {
61
62
  return defineIndexerPlugin<TFilter, TBlock>((indexer) => {
62
63
  let indexerId = "";
64
+ const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true";
63
65
 
64
66
  indexer.hooks.hook("run:before", async () => {
65
67
  const { indexerName } = useInternalContext();
66
68
  indexerId = generateIndexerId(indexerName, identifier);
69
+ const logger = useLogger();
70
+
71
+ if (alwaysReindex) {
72
+ logger.warn(
73
+ `Reindexing: Deleting all data from collections - ${collections.join(", ")}`,
74
+ );
75
+
76
+ await withTransaction(client, async (session) => {
77
+ const db = client.db(dbName, dbOptions);
78
+
79
+ await cleanupStorage(db, session, collections);
80
+
81
+ if (enablePersistence) {
82
+ await resetPersistence({ db, session, indexerId });
83
+ }
84
+
85
+ logger.success("All data has been cleaned up for reindexing");
86
+ });
87
+ }
67
88
 
68
89
  await withTransaction(client, async (session) => {
69
90
  const db = client.db(dbName, dbOptions);
package/src/mongo.ts CHANGED
@@ -49,3 +49,18 @@ export async function finalize(
49
49
  );
50
50
  }
51
51
  }
52
+
53
+ export async function cleanupStorage(
54
+ db: Db,
55
+ session: ClientSession,
56
+ collections: string[],
57
+ ) {
58
+ for (const collection of collections) {
59
+ try {
60
+ // Delete all documents in the collection
61
+ await db.collection(collection).deleteMany({}, { session });
62
+ } catch (error) {
63
+ throw new Error(`Failed to clean up collection ${collection}: ${error}`);
64
+ }
65
+ }
66
+ }
@@ -1,5 +1,6 @@
1
1
  import { type Cursor, normalizeCursor } from "@apibara/protocol";
2
2
  import type { ClientSession, Db } from "mongodb";
3
+ import { MongoStorageError } from "./utils";
3
4
 
4
5
  export type CheckpointSchema = {
5
6
  id: string;
@@ -161,3 +162,27 @@ export async function finalizeState(props: {
161
162
  { session },
162
163
  );
163
164
  }
165
+
166
+ export async function resetPersistence(props: {
167
+ db: Db;
168
+ session: ClientSession;
169
+ indexerId: string;
170
+ }) {
171
+ const { db, session, indexerId } = props;
172
+
173
+ try {
174
+ // Delete all checkpoints for this indexer
175
+ await db
176
+ .collection<CheckpointSchema>(checkpointCollectionName)
177
+ .deleteMany({ id: indexerId }, { session });
178
+
179
+ // Delete all filters for this indexer
180
+ await db
181
+ .collection<FilterSchema>(filterCollectionName)
182
+ .deleteMany({ id: indexerId }, { session });
183
+ } catch (error) {
184
+ throw new MongoStorageError("Failed to reset persistence state", {
185
+ cause: error,
186
+ });
187
+ }
188
+ }
package/src/utils.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { ClientSession, MongoClient } from "mongodb";
2
2
 
3
3
  export class MongoStorageError extends Error {
4
- constructor(message: string) {
5
- super(message);
4
+ constructor(message: string, options?: ErrorOptions) {
5
+ super(message, options);
6
6
  this.name = "MongoStorageError";
7
7
  }
8
8
  }