@apibara/plugin-mongo 2.1.0-beta.1 → 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 +49 -14
- package/dist/index.mjs +50 -15
- package/package.json +3 -3
- package/src/index.ts +23 -2
- package/src/mongo.ts +15 -0
- package/src/persistence.ts +25 -0
- package/src/utils.ts +2 -2
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.1.0-beta.
|
|
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.1.0-beta.
|
|
39
|
-
"@apibara/protocol": "2.1.0-beta.
|
|
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
|
+
}
|
package/src/persistence.ts
CHANGED
|
@@ -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
|
}
|