@filoz/repair-cli 0.1.1 → 0.2.0

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.
Files changed (109) hide show
  1. package/dist/package.json +3 -2
  2. package/dist/src/cli.js +2 -0
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/commands/datasets.d.ts +16 -1
  5. package/dist/src/commands/datasets.d.ts.map +1 -1
  6. package/dist/src/commands/datasets.js +107 -3
  7. package/dist/src/commands/datasets.js.map +1 -1
  8. package/dist/src/commands/providers.d.ts +16 -1
  9. package/dist/src/commands/providers.d.ts.map +1 -1
  10. package/dist/src/commands/providers.js.map +1 -1
  11. package/dist/src/commands/repair.d.ts +16 -1
  12. package/dist/src/commands/repair.d.ts.map +1 -1
  13. package/dist/src/commands/repair.js +7 -8
  14. package/dist/src/commands/repair.js.map +1 -1
  15. package/dist/src/commands/replicate.d.ts +24 -0
  16. package/dist/src/commands/replicate.d.ts.map +1 -0
  17. package/dist/src/commands/replicate.js +171 -0
  18. package/dist/src/commands/replicate.js.map +1 -0
  19. package/dist/src/commands/setup.d.ts.map +1 -1
  20. package/dist/src/commands/setup.js +15 -0
  21. package/dist/src/commands/setup.js.map +1 -1
  22. package/dist/src/commands/wallet.d.ts +16 -1
  23. package/dist/src/commands/wallet.d.ts.map +1 -1
  24. package/dist/src/db/dedupe-cids.d.ts +22 -0
  25. package/dist/src/db/dedupe-cids.d.ts.map +1 -0
  26. package/dist/src/db/dedupe-cids.js +28 -0
  27. package/dist/src/db/dedupe-cids.js.map +1 -0
  28. package/dist/src/db/find-providers-by-cid.d.ts +9 -0
  29. package/dist/src/db/find-providers-by-cid.d.ts.map +1 -0
  30. package/dist/src/db/{get-providers-by-cid.js → find-providers-by-cid.js} +4 -6
  31. package/dist/src/db/find-providers-by-cid.js.map +1 -0
  32. package/dist/src/db/find-repair-dataset.d.ts +10 -0
  33. package/dist/src/db/find-repair-dataset.d.ts.map +1 -0
  34. package/dist/src/db/{get-repair-dataset.js → find-repair-dataset.js} +8 -6
  35. package/dist/src/db/find-repair-dataset.js.map +1 -0
  36. package/dist/src/db/get-pieces.d.ts +16 -0
  37. package/dist/src/db/get-pieces.d.ts.map +1 -1
  38. package/dist/src/db/get-pieces.js +44 -3
  39. package/dist/src/db/get-pieces.js.map +1 -1
  40. package/dist/src/db/repair-create.d.ts.map +1 -1
  41. package/dist/src/db/repair-create.js +1 -0
  42. package/dist/src/db/repair-create.js.map +1 -1
  43. package/dist/src/db/repair-delete.d.ts.map +1 -1
  44. package/dist/src/db/repair-delete.js +0 -5
  45. package/dist/src/db/repair-delete.js.map +1 -1
  46. package/dist/src/db/replicate-create.d.ts +7 -0
  47. package/dist/src/db/replicate-create.d.ts.map +1 -0
  48. package/dist/src/db/replicate-create.js +78 -0
  49. package/dist/src/db/replicate-create.js.map +1 -0
  50. package/dist/src/db/upsert-operations.js +1 -1
  51. package/dist/src/db/upsert-operations.js.map +1 -1
  52. package/dist/src/local-schema.d.ts +19 -0
  53. package/dist/src/local-schema.d.ts.map +1 -1
  54. package/dist/src/local-schema.js +1 -0
  55. package/dist/src/local-schema.js.map +1 -1
  56. package/dist/src/middleware.d.ts +32 -2
  57. package/dist/src/middleware.d.ts.map +1 -1
  58. package/dist/src/middleware.js +10 -1
  59. package/dist/src/middleware.js.map +1 -1
  60. package/dist/src/pipeline/add-pieces.d.ts +12 -0
  61. package/dist/src/pipeline/add-pieces.d.ts.map +1 -0
  62. package/dist/src/pipeline/add-pieces.js +142 -0
  63. package/dist/src/pipeline/add-pieces.js.map +1 -0
  64. package/dist/src/pipeline/create-datasets.d.ts +3 -1
  65. package/dist/src/pipeline/create-datasets.d.ts.map +1 -1
  66. package/dist/src/pipeline/create-datasets.js +57 -5
  67. package/dist/src/pipeline/create-datasets.js.map +1 -1
  68. package/dist/src/utils.d.ts +166 -120
  69. package/dist/src/utils.d.ts.map +1 -1
  70. package/dist/src/utils.js +50 -25
  71. package/dist/src/utils.js.map +1 -1
  72. package/package.json +3 -2
  73. package/readme.md +110 -7
  74. package/src/cli.ts +2 -0
  75. package/src/commands/datasets.ts +109 -3
  76. package/src/commands/providers.ts +0 -1
  77. package/src/commands/repair.ts +12 -8
  78. package/src/commands/replicate.ts +183 -0
  79. package/src/commands/setup.ts +16 -0
  80. package/src/db/dedupe-cids.ts +49 -0
  81. package/src/db/{get-providers-by-cid.ts → find-providers-by-cid.ts} +5 -10
  82. package/src/db/{get-repair-dataset.ts → find-repair-dataset.ts} +12 -7
  83. package/src/db/get-pieces.ts +105 -3
  84. package/src/db/get-target-dataset.ts +1 -1
  85. package/src/db/repair-create.ts +1 -0
  86. package/src/db/repair-delete.ts +0 -5
  87. package/src/db/replicate-create.ts +106 -0
  88. package/src/db/upsert-operations.ts +1 -1
  89. package/src/local-schema.ts +1 -0
  90. package/src/middleware.ts +12 -1
  91. package/src/pipeline/add-pieces.ts +214 -0
  92. package/src/pipeline/create-datasets.ts +71 -11
  93. package/src/utils.ts +64 -32
  94. package/dist/src/db/get-providers-by-cid.d.ts +0 -10
  95. package/dist/src/db/get-providers-by-cid.d.ts.map +0 -1
  96. package/dist/src/db/get-providers-by-cid.js.map +0 -1
  97. package/dist/src/db/get-repair-dataset.d.ts +0 -9
  98. package/dist/src/db/get-repair-dataset.d.ts.map +0 -1
  99. package/dist/src/db/get-repair-dataset.js.map +0 -1
  100. package/dist/src/db/sync-pieces-onchain.d.ts +0 -10
  101. package/dist/src/db/sync-pieces-onchain.d.ts.map +0 -1
  102. package/dist/src/db/sync-pieces-onchain.js +0 -35
  103. package/dist/src/db/sync-pieces-onchain.js.map +0 -1
  104. package/dist/src/pipeline/pull.d.ts +0 -30
  105. package/dist/src/pipeline/pull.d.ts.map +0 -1
  106. package/dist/src/pipeline/pull.js +0 -169
  107. package/dist/src/pipeline/pull.js.map +0 -1
  108. package/src/db/sync-pieces-onchain.ts +0 -53
  109. package/src/pipeline/pull.ts +0 -255
@@ -0,0 +1,214 @@
1
+ import { taskLog } from '@clack/prompts'
2
+ import * as Piece from '@filoz/synapse-core/piece'
3
+ import * as SP from '@filoz/synapse-core/sp'
4
+ import { and, asc, eq, gt, inArray } from 'drizzle-orm'
5
+ import PQueue from 'p-queue'
6
+ import { dedupeCids } from '../db/dedupe-cids.ts'
7
+ import { getTargetDataset } from '../db/get-target-dataset.ts'
8
+ import { repairUpdate } from '../db/repair-update.ts'
9
+ import { upsertOperations } from '../db/upsert-operations.ts'
10
+ import type { OperationSelect, RepairSelect } from '../local-schema.ts'
11
+ import type { IndexerDatabase, LocalDatabase, WalletClient } from '../types.ts'
12
+ import { excludeOperationsByCid, hashLink, operationsToPullPieces } from '../utils.ts'
13
+
14
+ export type RunPullPiecesPhaseOptions = {
15
+ localDb: LocalDatabase
16
+ indexerDb: IndexerDatabase
17
+ repair: RepairSelect
18
+ concurrency: number
19
+ batchSize: number
20
+ client: WalletClient
21
+ }
22
+
23
+ type CreateAddPiecesWorkerOptions = {
24
+ localDb: LocalDatabase
25
+ indexerDb: IndexerDatabase
26
+ repair: RepairSelect
27
+ client: WalletClient
28
+ state: {
29
+ totalBatches: number
30
+ totalOperations: number
31
+ completedOperations: number
32
+ failedOperations: number
33
+ }
34
+ log: ReturnType<typeof taskLog>
35
+ }
36
+
37
+ type AddPiecesJobOptions = {
38
+ operations: OperationSelect[]
39
+ batchNumber: number
40
+ }
41
+
42
+ /**
43
+ * Create a worker function that adds pieces to the target repair dataset.
44
+ */
45
+ function createAddPiecesWorker({ localDb, indexerDb, repair, client, state, log }: CreateAddPiecesWorkerOptions) {
46
+ return async (options: AddPiecesJobOptions) => {
47
+ let completedOps = 0
48
+ let failedOps = 0
49
+ let operations: OperationSelect[] = options.operations
50
+
51
+ const group = log.group(`Batch ${options.batchNumber}/${state.totalBatches}`)
52
+
53
+ try {
54
+ const dataset = await getTargetDataset({ localDb, repairId: repair.id, client })
55
+
56
+ // dedupe operations by CID on the target dataset for repairs jobs
57
+ if (repair.repairDataSetId == null) {
58
+ operations = await dedupeCids({ indexerDb, localDb, dataSetId: dataset.dataSetId, operations })
59
+ }
60
+ group.message(`Pulling ${operations.length} pieces...`)
61
+ // pull pieces
62
+ if (operations.length > 0) {
63
+ const pullResult = await SP.waitForPullPieces(client, {
64
+ serviceURL: repair.targetProviderUrl,
65
+ dataSetId: dataset.dataSetId,
66
+ clientDataSetId: dataset.clientDataSetId,
67
+ pieces: operationsToPullPieces(operations),
68
+ timeout: 1000 * 60 * 30,
69
+ onStatus: (status) => {
70
+ const completed = status.pieces.filter((piece) => piece.status === 'complete').length
71
+ const failed = status.pieces.filter((piece) => piece.status === 'failed').length
72
+ group.message(`Pull ${completed} completed, ${failed} failed`)
73
+ },
74
+ })
75
+
76
+ for (const { pieceCid, status } of pullResult.pieces) {
77
+ const cid = pieceCid.toString()
78
+ if (status !== 'complete') {
79
+ state.failedOperations++
80
+ failedOps++
81
+ const { operationToFailed, operationToCommit } = excludeOperationsByCid(operations, cid)
82
+ operations = operationToCommit
83
+ await upsertOperations({
84
+ localDb,
85
+ operations: operationToFailed.map((operation) => ({
86
+ ...operation,
87
+ status: 'failed',
88
+ error: `pull failed with status ${status}`,
89
+ })),
90
+ })
91
+ }
92
+ }
93
+ }
94
+
95
+ // add pieces
96
+ if (operations.length > 0) {
97
+ group.message(`Adding ${operations.length} pieces...`)
98
+ const addPiecesResult = await SP.addPieces(client, {
99
+ serviceURL: repair.targetProviderUrl,
100
+ dataSetId: dataset.dataSetId,
101
+ clientDataSetId: dataset.clientDataSetId,
102
+ pieces: operations.map((operation) => ({
103
+ pieceCid: Piece.from(operation.cid),
104
+ metadata: operation.metadata,
105
+ })),
106
+ })
107
+
108
+ group.message(`Waiting for add pieces ${hashLink(addPiecesResult.txHash, client.chain)}...`)
109
+ const addPiecesResult2 = await SP.waitForAddPieces(addPiecesResult)
110
+ state.completedOperations += operations.length
111
+ completedOps += operations.length
112
+ await upsertOperations({
113
+ localDb,
114
+ operations: operations.map((operation) => ({
115
+ ...operation,
116
+ status: 'completed',
117
+ error: null,
118
+ result: { dataSetId: addPiecesResult2.dataSetId, txHash: addPiecesResult2.txHash },
119
+ })),
120
+ })
121
+ }
122
+ group.message(`Done. ${completedOps} added, ${failedOps} failed`)
123
+ } catch (error) {
124
+ state.failedOperations += operations.length
125
+ const message = error instanceof Error ? error.message : 'Unknown error'
126
+ group.message(`${message.replace(/\n/g, ' ')}`)
127
+ await upsertOperations({
128
+ localDb,
129
+ operations: operations.map((operation) => ({
130
+ ...operation,
131
+ status: 'failed',
132
+ error: message,
133
+ })),
134
+ })
135
+ }
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Add pieces to the target dataset.
141
+ */
142
+ export async function runAddPieces({
143
+ localDb,
144
+ indexerDb,
145
+ repair,
146
+ concurrency,
147
+ batchSize,
148
+ client,
149
+ }: RunPullPiecesPhaseOptions): Promise<void> {
150
+ const localSchema = localDb._.fullSchema
151
+ let cursor = 0
152
+
153
+ const totalOperations = await localDb.$count(
154
+ localSchema.operations,
155
+ and(
156
+ eq(localSchema.operations.repairId, repair.id),
157
+ eq(localSchema.operations.type, 'add_piece'),
158
+ inArray(localSchema.operations.status, ['pending', 'failed'])
159
+ )
160
+ )
161
+ let batchNumber = 0
162
+ const state = {
163
+ totalBatches: Math.ceil(totalOperations / batchSize),
164
+ totalOperations,
165
+ completedOperations: 0,
166
+ failedOperations: 0,
167
+ }
168
+
169
+ const log = taskLog({
170
+ title: 'Adding pieces',
171
+ limit: 1,
172
+ })
173
+
174
+ async function getNextBatch(): Promise<OperationSelect[] | null> {
175
+ const operations = await localDb.query.operations.findMany({
176
+ where: and(
177
+ eq(localSchema.operations.repairId, repair.id),
178
+ eq(localSchema.operations.type, 'add_piece'),
179
+ inArray(localSchema.operations.status, ['pending', 'failed']),
180
+ gt(localSchema.operations.id, cursor)
181
+ ),
182
+ orderBy: [asc(localSchema.operations.id)],
183
+ limit: batchSize,
184
+ })
185
+ if (operations.length === 0) {
186
+ return null
187
+ }
188
+
189
+ cursor = operations.at(-1)?.id ?? cursor
190
+ return operations
191
+ }
192
+
193
+ const addPiecesJob = createAddPiecesWorker({ localDb, indexerDb, repair, client, state, log })
194
+ const queue = new PQueue({ concurrency })
195
+
196
+ while (true) {
197
+ await queue.onSizeLessThan(concurrency)
198
+ const operations = await getNextBatch()
199
+ if (!operations) break
200
+ batchNumber++
201
+ const currentBatchNumber = batchNumber
202
+ queue.add(() => addPiecesJob({ operations, batchNumber: currentBatchNumber })).catch(console.error)
203
+ }
204
+
205
+ await queue.onIdle()
206
+
207
+ log.success(`Added ${state.completedOperations} pieces, ${state.failedOperations} failed`, { showLog: true })
208
+
209
+ await repairUpdate({
210
+ localDb,
211
+ repairId: repair.id,
212
+ status: state.failedOperations > 0 ? 'failed' : 'completed',
213
+ })
214
+ }
@@ -1,13 +1,15 @@
1
1
  import * as p from '@clack/prompts'
2
2
  import * as SP from '@filoz/synapse-core/sp'
3
3
  import { getPDPProvider } from '@filoz/synapse-core/sp-registry'
4
- import { getRepairDataset } from '../db/get-repair-dataset.ts'
4
+ import { eq } from 'drizzle-orm'
5
+ import { findRepairDataset } from '../db/find-repair-dataset.ts'
5
6
  import { repairUpdate } from '../db/repair-update.ts'
6
7
  import type { RepairSelect } from '../local-schema.ts'
7
8
  import type { IndexerDatabase, LocalDatabase, WalletClient } from '../types.ts'
8
- import { getRepairDatasetMetadata, hashLink } from '../utils.ts'
9
+ import { hashLink } from '../utils.ts'
9
10
 
10
11
  export type EnsureRepairDatasetOptions = {
12
+ source: string
11
13
  localDb: LocalDatabase
12
14
  indexerDb: IndexerDatabase
13
15
  client: WalletClient
@@ -18,14 +20,8 @@ export type EnsureRepairDatasetOptions = {
18
20
  * Ensure the repair dataset exists by creating it if it doesn't.
19
21
  *
20
22
  * @param options - The options for ensuring the repair dataset.
21
- * @returns {Promise<bigint>} - The ID of the created dataset.
22
23
  */
23
- export async function ensureRepairDataset({
24
- localDb,
25
- indexerDb,
26
- client,
27
- repair,
28
- }: EnsureRepairDatasetOptions): Promise<bigint> {
24
+ export async function ensureRepairDataset({ source, localDb, indexerDb, client, repair }: EnsureRepairDatasetOptions) {
29
25
  const log = p.taskLog({
30
26
  title: 'Ensuring repair dataset',
31
27
  })
@@ -37,10 +33,11 @@ export async function ensureRepairDataset({
37
33
 
38
34
  let datasetId: bigint | null = null
39
35
  // check if dataset already exists
40
- const existingDatasetId = await getRepairDataset({
36
+ const existingDatasetId = await findRepairDataset({
41
37
  indexerDb,
42
38
  providerId: repair.targetProviderId,
43
39
  payer: client.account.address,
40
+ source,
44
41
  })
45
42
 
46
43
  if (existingDatasetId) {
@@ -52,7 +49,10 @@ export async function ensureRepairDataset({
52
49
  serviceURL: provider.pdp.serviceURL,
53
50
  payer: client.account.address,
54
51
  cdn: false,
55
- metadata: getRepairDatasetMetadata(),
52
+ metadata: {
53
+ source,
54
+ withIPFSIndexing: '',
55
+ },
56
56
  })
57
57
  log.message(`Waiting for data to be created at ${provider.pdp.serviceURL} ${hashLink(txHash, client.chain)}...`)
58
58
  const waitForResult = await SP.waitForCreateDataSet({
@@ -68,3 +68,63 @@ export async function ensureRepairDataset({
68
68
  })
69
69
  return datasetId
70
70
  }
71
+
72
+ /**
73
+ * Ensure a replication target dataset exists by creating a fresh dataset with source metadata.
74
+ *
75
+ * @param options - The options for ensuring the replication dataset.
76
+ */
77
+ export async function ensureReplicateDataset({ localDb, indexerDb, client, repair }: EnsureRepairDatasetOptions) {
78
+ const log = p.taskLog({
79
+ title: 'Ensuring replication dataset',
80
+ })
81
+
82
+ if (repair.repairDataSetId == null) {
83
+ throw new Error('Missing source dataset ID')
84
+ }
85
+
86
+ const provider = await getPDPProvider(client, {
87
+ providerId: repair.targetProviderId,
88
+ })
89
+
90
+ if (!provider) throw new Error(`Target provider ${repair.targetProviderId} not found or inactive`)
91
+
92
+ if (repair.targetDataSetId != null) {
93
+ log.success(`Data set #${repair.targetDataSetId} already exists at ${provider.pdp.serviceURL}`)
94
+ return repair.targetDataSetId
95
+ }
96
+
97
+ const schema = indexerDb._.fullSchema
98
+ const sourceDataSet = await indexerDb.query.dataSets.findFirst({
99
+ where: eq(schema.dataSets.dataSetId, repair.repairDataSetId),
100
+ columns: {
101
+ metadata: true,
102
+ withCdn: true,
103
+ },
104
+ })
105
+
106
+ if (!sourceDataSet) {
107
+ throw new Error(`Source dataset ${repair.repairDataSetId} not found`)
108
+ }
109
+
110
+ const { txHash, statusUrl } = await SP.createDataSet(client, {
111
+ payee: provider.payee,
112
+ serviceURL: provider.pdp.serviceURL,
113
+ payer: client.account.address,
114
+ cdn: sourceDataSet.withCdn,
115
+ metadata: sourceDataSet.metadata ?? undefined,
116
+ })
117
+ log.message(`Waiting for data to be created at ${provider.pdp.serviceURL} ${hashLink(txHash, client.chain)}...`)
118
+ const waitForResult = await SP.waitForCreateDataSet({
119
+ statusUrl,
120
+ })
121
+ const datasetId = waitForResult.dataSetId
122
+ log.success(`Data set #${datasetId} created at ${provider.pdp.serviceURL}`)
123
+
124
+ await repairUpdate({
125
+ localDb,
126
+ repairId: repair.id,
127
+ targetDataSetId: datasetId,
128
+ })
129
+ return datasetId
130
+ }
package/src/utils.ts CHANGED
@@ -1,42 +1,36 @@
1
1
  import type { MetadataObject } from '@filoz/synapse-core'
2
2
  import { type Chain, getChain } from '@filoz/synapse-core/chains'
3
- import Conf from 'conf'
3
+ import * as Piece from '@filoz/synapse-core/piece'
4
+ import type * as SP from '@filoz/synapse-core/sp'
4
5
  import { getTableColumns, type SQL, sql } from 'drizzle-orm'
5
6
  import { drizzle } from 'drizzle-orm/libsql'
6
7
  import type { PgTable } from 'drizzle-orm/pg-core'
7
8
  import type { SQLiteTable } from 'drizzle-orm/sqlite-core'
8
9
  import { z } from 'incur'
10
+ import { Conf } from 'iso-conf'
9
11
  import { request } from 'iso-web/http'
10
12
  import pLocate from 'p-locate'
11
13
  import terminalLink from 'terminal-link'
12
- import { createWalletClient, http } from 'viem'
14
+ import { createWalletClient, type Hex, http } from 'viem'
13
15
  import { privateKeyToAccount } from 'viem/accounts'
14
16
  import packageJson from '../package.json' with { type: 'json' }
17
+ import type { OperationSelect } from './local-schema.ts'
15
18
  import * as schema from './local-schema.ts'
16
- import type { Config, LocalDatabase } from './types.ts'
17
-
18
- export const EARLY_REPAIR_SOURCE = 'early-repair6'
19
+ import type { LocalDatabase } from './types.ts'
20
+
21
+ export const configSchema = z.object({
22
+ privateKey: z.string().optional(),
23
+ indexerMainnetUrl: z.url().optional(),
24
+ indexerCalibrationUrl: z.url().optional(),
25
+ chainId: z.number().optional(),
26
+ dbPath: z.string().optional(),
27
+ source: z.string().optional(),
28
+ })
19
29
 
20
- export const config = new Conf<Config>({
30
+ export const config = new Conf({
21
31
  projectName: packageJson.name,
22
32
  projectSuffix: '',
23
- schema: {
24
- privateKey: {
25
- type: 'string',
26
- },
27
- dbPath: {
28
- type: 'string',
29
- },
30
- indexerMainnetUrl: {
31
- type: 'string',
32
- },
33
- indexerCalibrationUrl: {
34
- type: 'string',
35
- },
36
- chainId: {
37
- type: 'number',
38
- },
39
- },
33
+ schema: configSchema,
40
34
  })
41
35
 
42
36
  export const name = packageJson.name
@@ -47,7 +41,7 @@ function privateKeyFromConfig() {
47
41
  if (!privateKey) {
48
42
  throw new Error('Private key not found. Please run `repair-cli setup` first.')
49
43
  }
50
- return privateKey
44
+ return privateKey as Hex
51
45
  }
52
46
 
53
47
  /**
@@ -102,11 +96,19 @@ export async function migrateLocalDatabase(db: LocalDatabase) {
102
96
  target_provider_id text NOT NULL,
103
97
  target_provider_url text NOT NULL,
104
98
  target_data_set_id text,
99
+ repair_data_set_id text,
105
100
  block_number text NOT NULL,
106
101
  created_at integer NOT NULL,
107
102
  updated_at integer NOT NULL
108
103
  )
109
104
  `)
105
+ try {
106
+ await db.$client.execute(`
107
+ ALTER TABLE repairs ADD COLUMN repair_data_set_id text
108
+ `)
109
+ } catch {
110
+ // Column already exists on databases created with the updated schema.
111
+ }
110
112
  await db.$client.execute(`
111
113
  CREATE TABLE IF NOT EXISTS operations (
112
114
  id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -137,14 +139,6 @@ export function hashLink(hash: string, chain: Chain) {
137
139
  return link
138
140
  }
139
141
 
140
- /** Get metadata for the single IPFS-enabled repair dataset. */
141
- export function getRepairDatasetMetadata(): MetadataObject {
142
- return {
143
- source: EARLY_REPAIR_SOURCE,
144
- withIPFSIndexing: '',
145
- }
146
- }
147
-
148
142
  /**
149
143
  * Get a piece from a service URL
150
144
  */
@@ -207,3 +201,41 @@ export const buildConflictUpdateColumns = <T extends PgTable | SQLiteTable, Q ex
207
201
 
208
202
  return r
209
203
  }
204
+
205
+ /**
206
+ * Filter out operations by CID
207
+ */
208
+ export function excludeOperationsByCid(operations: OperationSelect[], cid: string) {
209
+ const operationToCommit: OperationSelect[] = []
210
+ const operationToFailed: OperationSelect[] = []
211
+ for (const operation of operations) {
212
+ if (operation.cid === cid) {
213
+ operationToFailed.push(operation)
214
+ } else {
215
+ operationToCommit.push(operation)
216
+ }
217
+ }
218
+ return { operationToCommit, operationToFailed }
219
+ }
220
+
221
+ /**
222
+ * Convert operations to pull pieces deduped by CID
223
+ */
224
+ export function operationsToPullPieces(operations: OperationSelect[]) {
225
+ const cids = new Set<string>()
226
+ const pieces: SP.PullPieceInput[] = []
227
+ for (const operation of operations) {
228
+ if (cids.has(operation.cid)) {
229
+ continue
230
+ }
231
+ pieces.push({
232
+ sourceUrl: Piece.createPieceUrlPDP({
233
+ cid: operation.cid,
234
+ serviceURL: operation.alternateProvider,
235
+ }),
236
+ pieceCid: Piece.from(operation.cid),
237
+ })
238
+ cids.add(operation.cid)
239
+ }
240
+ return pieces
241
+ }
@@ -1,10 +0,0 @@
1
- import type { IndexerDatabase, RepairProvider } from '../types.ts';
2
- export type GetProvidersByCidOptions = {
3
- indexerDb: IndexerDatabase;
4
- cids: readonly string[];
5
- excludedProviderIds: readonly bigint[];
6
- blockNumber: bigint;
7
- };
8
- export type ProvidersByCid = Record<string, RepairProvider[]>;
9
- export declare function getProvidersByCid({ indexerDb, cids, excludedProviderIds, blockNumber, }: GetProvidersByCidOptions): Promise<ProvidersByCid>;
10
- //# sourceMappingURL=get-providers-by-cid.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-providers-by-cid.d.ts","sourceRoot":"","sources":["../../../src/db/get-providers-by-cid.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAElE,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,eAAe,CAAA;IAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAKD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAA;AAS7D,wBAAsB,iBAAiB,CAAC,EACtC,SAAS,EACT,IAAI,EACJ,mBAAmB,EACnB,WAAW,GACZ,EAAE,wBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CA+CpD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-providers-by-cid.js","sourceRoot":"","sources":["../../../src/db/get-providers-by-cid.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- import type { Address } from 'viem';
2
- import type { IndexerDatabase } from '../types.ts';
3
- export type GetRepairDatasetOptions = {
4
- indexerDb: IndexerDatabase;
5
- providerId: bigint;
6
- payer: Address;
7
- };
8
- export declare function getRepairDataset({ indexerDb, providerId, payer, }: GetRepairDatasetOptions): Promise<bigint | null>;
9
- //# sourceMappingURL=get-repair-dataset.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-repair-dataset.d.ts","sourceRoot":"","sources":["../../../src/db/get-repair-dataset.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAGlD,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,eAAe,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAOD,wBAAsB,gBAAgB,CAAC,EACrC,SAAS,EACT,UAAU,EACV,KAAK,GACN,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuBlD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-repair-dataset.js","sourceRoot":"","sources":["../../../src/db/get-repair-dataset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGlD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAajD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,SAAS,EACT,UAAU,EACV,KAAK,GACmB;IACxB,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,UAAU,CAAA;IAErC,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,SAAS;SAC1B,MAAM,CAAC;QACN,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS;KACrC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;SACrB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,EAC1C,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,EAClC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EACnC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,EAC9C,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC/C,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,EAClC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAC3C,CACF;SACA,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;SACvC,KAAK,CAAC,CAAC,CAAC,CAAA;IAEX,OAAO,GAAG,CAAC,SAAS,IAAI,IAAI,CAAA;AAC9B,CAAC"}
@@ -1,10 +0,0 @@
1
- import type { OperationSelect } from '../local-schema.ts';
2
- import type { IndexerDatabase, LocalDatabase } from '../types.ts';
3
- export type SyncPiecesOnchainOptions = {
4
- indexerDb: IndexerDatabase;
5
- localDb: LocalDatabase;
6
- dataSetId: bigint;
7
- cidToOperation: Map<string, OperationSelect>;
8
- };
9
- export declare function syncPiecesOnchain({ indexerDb, localDb, dataSetId, cidToOperation }: SyncPiecesOnchainOptions): Promise<number>;
10
- //# sourceMappingURL=sync-pieces-onchain.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sync-pieces-onchain.d.ts","sourceRoot":"","sources":["../../../src/db/sync-pieces-onchain.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGjE,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,eAAe,CAAA;IAC1B,OAAO,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAC7C,CAAA;AAKD,wBAAsB,iBAAiB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,wBAAwB,mBAqClH"}
@@ -1,35 +0,0 @@
1
- import { and, eq, inArray } from 'drizzle-orm';
2
- import { upsertOperations } from "./upsert-operations.js";
3
- export async function syncPiecesOnchain({ indexerDb, localDb, dataSetId, cidToOperation }) {
4
- const cids = Array.from(cidToOperation.keys());
5
- const schema = indexerDb._.fullSchema;
6
- let completedOperations = 0;
7
- const rows = await indexerDb
8
- .select({ cid: schema.pieces.cid })
9
- .from(schema.pieces)
10
- .where(and(eq(schema.pieces.dataSetId, dataSetId), eq(schema.pieces.removed, false), inArray(schema.pieces.cid, cids)));
11
- const existingCids = new Set();
12
- const completedOperation = [];
13
- for (const row of rows) {
14
- const operation = cidToOperation.get(row.cid);
15
- if (!operation) {
16
- continue;
17
- }
18
- completedOperation.push({
19
- ...operation,
20
- status: 'completed',
21
- error: null,
22
- });
23
- existingCids.add(row.cid);
24
- cidToOperation.delete(row.cid);
25
- completedOperations++;
26
- }
27
- if (completedOperation.length > 0) {
28
- await upsertOperations({
29
- localDb,
30
- operations: completedOperation,
31
- });
32
- }
33
- return completedOperations;
34
- }
35
- //# sourceMappingURL=sync-pieces-onchain.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sync-pieces-onchain.js","sourceRoot":"","sources":["../../../src/db/sync-pieces-onchain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAG9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAYzD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAA4B;IACjH,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,UAAU,CAAA;IACrC,IAAI,mBAAmB,GAAG,CAAC,CAAA;IAC3B,MAAM,IAAI,GAAG,MAAM,SAAS;SACzB,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;SAClC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;SACnB,KAAK,CACJ,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAChH,CAAA;IAEH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IACtC,MAAM,kBAAkB,GAAsB,EAAE,CAAA;IAEhD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC7C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,SAAQ;QACV,CAAC;QACD,kBAAkB,CAAC,IAAI,CAAC;YACtB,GAAG,SAAS;YACZ,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI;SACZ,CAAC,CAAA;QACF,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACzB,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC9B,mBAAmB,EAAE,CAAA;IACvB,CAAC;IAED,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,gBAAgB,CAAC;YACrB,OAAO;YACP,UAAU,EAAE,kBAAkB;SAC/B,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,mBAAmB,CAAA;AAC5B,CAAC"}
@@ -1,30 +0,0 @@
1
- import { taskLog } from '@clack/prompts';
2
- import type { OperationSelect, RepairSelect } from '../local-schema.ts';
3
- import type { IndexerDatabase, LocalDatabase, WalletClient } from '../types.ts';
4
- export type PullPiecesBatch = {
5
- operations: OperationSelect[];
6
- };
7
- export type RunPullPiecesPhaseOptions = {
8
- localDb: LocalDatabase;
9
- indexerDb: IndexerDatabase;
10
- repair: RepairSelect;
11
- concurrency: number;
12
- batchSize: number;
13
- client: WalletClient;
14
- reset: boolean;
15
- };
16
- export declare function createPullPiecesWorker({ localDb, indexerDb, repair, client, state, log, }: {
17
- localDb: LocalDatabase;
18
- indexerDb: IndexerDatabase;
19
- repair: RepairSelect;
20
- client: WalletClient;
21
- state: {
22
- totalBatches: number;
23
- totalOperations: number;
24
- completedOperations: number;
25
- failedOperations: number;
26
- };
27
- log: ReturnType<typeof taskLog>;
28
- }): (batch: PullPiecesBatch, batchNumber: number) => Promise<void>;
29
- export declare function runPullPiecesPhase({ localDb, indexerDb, repair, concurrency, batchSize, client, reset, }: RunPullPiecesPhaseOptions): Promise<void>;
30
- //# sourceMappingURL=pull.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/pipeline/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAUxC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI/E,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,eAAe,EAAE,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,eAAe,CAAA;IAC1B,MAAM,EAAE,YAAY,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAGD,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,SAAS,EACT,MAAM,EACN,MAAM,EACN,KAAK,EACL,GAAG,GACJ,EAAE;IACD,OAAO,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,eAAe,CAAA;IAC1B,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAA;QACpB,eAAe,EAAE,MAAM,CAAA;QACvB,mBAAmB,EAAE,MAAM,CAAA;QAC3B,gBAAgB,EAAE,MAAM,CAAA;KACzB,CAAA;IACD,GAAG,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,CAAA;CAChC,IACe,OAAO,eAAe,EAAE,aAAa,MAAM,mBA+H1D;AAQD,wBAAsB,kBAAkB,CAAC,EACvC,OAAO,EACP,SAAS,EACT,MAAM,EACN,WAAW,EACX,SAAS,EACT,MAAM,EACN,KAAK,GACN,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D3C"}