UNPKG

@sanity/import

Version:

Import documents to a Sanity dataset

138 lines (137 loc) 4.66 kB
import pMap from 'p-map'; import { progressStepper } from './util/progressStepper.js'; import { retryOnFailure } from './util/retryOnFailure.js'; import { suffixTag } from './util/suffixTag.js'; const DOCUMENT_IMPORT_CONCURRENCY = 6; const RELEASE_IMPORT_CONCURRENCY = 3; export async function importBatches(batches, options) { const progress = progressStepper(options.onProgress, { step: 'Importing documents', total: batches.length }); const mapOptions = { concurrency: DOCUMENT_IMPORT_CONCURRENCY }; const batchResults = await pMap(batches, importBatch.bind(null, options, progress), mapOptions); const result = { count: 0, importedIds: [] }; for (const batchResult of batchResults){ result.count += batchResult.count; result.importedIds = [ ...result.importedIds, ...batchResult.importedIds ]; } return result; } function importBatch(options, progress, batch) { const { client, operation, releasesOperation, tag } = options; const maxRetries = operation === 'create' ? 1 : 3; return retryOnFailure(async ()=>{ const releaseDocs = []; const docs = []; for (const doc of batch){ if (doc._id.startsWith('_.releases.')) { releaseDocs.push(doc); } else { docs.push(doc); } } const docsTransaction = docs.length > 0 ? (()=>{ let trx = client.transaction(); for (const doc of docs){ switch(operation){ case 'create': { trx = trx.create(doc); break; } case 'createIfNotExists': { trx = trx.createIfNotExists(doc); break; } case 'createOrReplace': { trx = trx.createOrReplace(doc); break; } default: { throw new Error(`Unknown operation: ${operation}`); } } } return trx; })().commit({ tag: suffixTag(tag, 'doc.create'), visibility: 'async' }).then((res)=>{ progress(); const importedIds = res.results.filter((r)=>r.operation !== 'none').map((r)=>r.id); return { count: res.results.length, importedIds }; }) : Promise.resolve({ count: 0, importedIds: [] }); const releaseResults = releaseDocs.length > 0 ? await pMap(releaseDocs, (doc)=>{ const actionParams = { actionType: 'sanity.action.release.import', attributes: doc, ifExists: releasesOperation, releaseId: doc.name }; return client.action(actionParams).then(()=>({ count: 1, importedIds: [ doc._id ] })).catch((err)=>{ err.message = `Release import failed for ${doc._id}: ${err.message}`; throw err; }); }, { concurrency: RELEASE_IMPORT_CONCURRENCY, stopOnError: false }).catch((err)=>{ if (err instanceof AggregateError) { const permissionError = err.errors.find((e)=>e.response?.statusCode === 403 || e.statusCode === 403); throw permissionError || err.errors[0]; } throw err; }) : []; const docsResult = await docsTransaction; const combined = { count: 0, importedIds: [] }; for (const r of [ docsResult, ...releaseResults ]){ combined.count += r.count; combined.importedIds = [ ...combined.importedIds, ...r.importedIds ]; } return combined; }, { isRetriable, maxTries: maxRetries }); } function isRetriable(err) { const statusCode = err.response?.statusCode ?? err.statusCode; // 409 Conflict and 403 Forbidden are not retriable if (statusCode === 409 || statusCode === 403) { return false; } return true; } //# sourceMappingURL=importBatches.js.map