-
Notifications
You must be signed in to change notification settings - Fork 9
fix: pieces can be removed from a data-set #253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
93d32ae
fix: pieces can be removed from a data-set
SgtPooki 9abd9ea
Merge branch 'master' into 8-add-rm---piece-piececid-command
SgtPooki 09a2f91
fix: handle pieces pending removal
SgtPooki e7e2fc4
fix: display piece onchain vs pdpserver status
SgtPooki 2c4b84f
fix: rm cmd requires --piece and --data-set
SgtPooki ffd4d01
fix: fix default to orphaned piece status
SgtPooki d139558
Merge branch 'master' into 8-add-rm---piece-piececid-command
SgtPooki 9069e21
deps: upgrade to latest synapse
SgtPooki 28c0883
fix: use new createStorageContext signature in rm
SgtPooki 2d9fc7f
test: fix mock merge issue
SgtPooki 01f6e6c
chore: remove unnecessary as string casting
SgtPooki b60eae6
fix: logger is no longer required for createStorageContext
SgtPooki 6fcb9d6
test: remove-piece is tested
SgtPooki 362cca6
test: assert runRmPiece happy path
SgtPooki 6e372f6
chore: remove outdated comment
SgtPooki e77693f
Update src/core/data-set/get-detailed-data-set.ts
SgtPooki 414aec3
Update src/rm/remove-piece.ts
SgtPooki 2198e51
Update src/rm/remove-piece.ts
SgtPooki a66dd7a
Update src/rm/remove-piece.ts
SgtPooki 797def7
chore: update jsdoc comments in runRmPiece
SgtPooki f0450a2
fix: removePiece requires storageContext
SgtPooki f8c977f
fix: document more about piece orphans
SgtPooki c2a60d3
Update src/core/data-set/types.ts
SgtPooki f31e0ed
Update src/rm/remove-piece.ts
SgtPooki 701a78c
fix: export Warning type
SgtPooki File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { Command } from 'commander' | ||
| import { runRmPiece } from '../rm/index.js' | ||
| import { addAuthOptions } from '../utils/cli-options.js' | ||
|
|
||
| export const rmCommand = new Command('rm') | ||
| .description('Remove a Piece from a DataSet') | ||
| .option('--piece <cid>', 'Piece CID to remove') | ||
| .option('--data-set <id>', 'DataSet ID to remove the piece from') | ||
| .option('--wait-for-confirmation', 'Wait for transaction confirmation before exiting') | ||
| .action(async (options) => { | ||
| try { | ||
| await runRmPiece(options) | ||
| } catch { | ||
| // Error already displayed by clack UI in runRmPiece | ||
SgtPooki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| process.exit(1) | ||
| } | ||
| }) | ||
|
|
||
| addAuthOptions(rmCommand) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './remove-piece.js' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| /** | ||
| * Remove piece functionality | ||
| * | ||
| * This module demonstrates the pattern for removing pieces from Data Sets | ||
| * via Synapse SDK. It supports two usage patterns: | ||
| * | ||
| * 1. With dataSetId - creates a temporary storage context (CLI usage) | ||
| * 2. With existing StorageContext - reuses context (library/server usage) | ||
| * | ||
| * Progress events allow callers to track transaction submission and confirmation. | ||
| */ | ||
| import type { StorageContext, Synapse } from '@filoz/synapse-sdk' | ||
| import type { Logger } from 'pino' | ||
| import { createStorageContext } from '../synapse/index.js' | ||
| import { getErrorMessage } from '../utils/errors.js' | ||
| import type { ProgressEvent, ProgressEventHandler } from '../utils/types.js' | ||
|
|
||
| /** | ||
| * Progress events emitted during piece removal | ||
| * | ||
| * These events allow callers to track the removal process: | ||
| * - submitting: Transaction is being submitted to blockchain | ||
| * - submitted: Transaction submitted successfully, txHash available | ||
| * - confirming: Waiting for transaction confirmation (if waitForConfirmation=true) | ||
| * - confirmation-failed: Confirmation wait timed out (non-fatal, tx may still succeed) | ||
| * - complete: Removal process finished | ||
| * | ||
| * Note: Errors are propagated via thrown exceptions, not events (similar to upload pattern) | ||
| */ | ||
| export type RemovePieceProgressEvents = | ||
| | ProgressEvent<'remove-piece:submitting', { pieceCid: string; dataSetId: number }> | ||
| | ProgressEvent<'remove-piece:submitted', { pieceCid: string; dataSetId: number; txHash: `0x${string}` | string }> | ||
| | ProgressEvent<'remove-piece:confirming', { pieceCid: string; dataSetId: number; txHash: `0x${string}` | string }> | ||
| | ProgressEvent< | ||
| 'remove-piece:confirmation-failed', | ||
| { pieceCid: string; dataSetId: number; txHash: `0x${string}` | string; message: string } | ||
| > | ||
| | ProgressEvent<'remove-piece:complete', { txHash: `0x${string}` | string; confirmed: boolean }> | ||
|
|
||
| /** | ||
| * Number of block confirmations to wait for when waitForConfirmation=true | ||
| */ | ||
| const WAIT_CONFIRMATIONS = 1 | ||
|
|
||
| /** | ||
| * Timeout in milliseconds for waiting for transaction confirmation | ||
| * Set to 2 minutes - generous default for Calibration network finality | ||
| */ | ||
| const WAIT_TIMEOUT_MS = 2 * 60 * 1000 | ||
|
|
||
| /** | ||
| * Base options for piece removal | ||
| */ | ||
| interface RemovePieceOptionsBase { | ||
| /** Initialized Synapse SDK instance */ | ||
| synapse: Synapse | ||
| /** Optional progress event handler for tracking removal status */ | ||
| onProgress?: ProgressEventHandler<RemovePieceProgressEvents> | undefined | ||
| /** Whether to wait for transaction confirmation before returning (default: false) */ | ||
| waitForConfirmation?: boolean | undefined | ||
| /** Optional logger for tracking removal operations */ | ||
| logger?: Logger | undefined | ||
| } | ||
|
|
||
| /** | ||
| * Options for removing a piece when you have a dataSetId | ||
| * | ||
| * This is the typical CLI usage pattern - you know the dataSetId and want | ||
| * to remove a piece from it. A temporary storage context will be created. | ||
| * | ||
| * Note: logger is required in this mode for storage context creation. | ||
SgtPooki marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| */ | ||
| interface RemovePieceOptionsWithDataSetId extends RemovePieceOptionsBase { | ||
| /** The Data Set ID containing the piece to remove */ | ||
| dataSetId: number | ||
| /** | ||
| * Logger instance (required for storage context creation) | ||
| * @see https://github.com/filecoin-project/filecoin-pin/issues/252 | ||
| */ | ||
| logger: Logger | ||
| } | ||
|
|
||
| /** | ||
| * Options for removing a piece when you have an existing StorageContext | ||
| * | ||
| * This is useful for library/server usage where you already have a storage | ||
| * context and want to remove multiple pieces without recreating the context. | ||
| */ | ||
| interface RemovePieceOptionsWithStorage extends RemovePieceOptionsBase { | ||
| /** Existing storage context bound to a Data Set */ | ||
| storage: StorageContext | ||
| } | ||
|
|
||
| /** | ||
| * Options for removing a piece from a Data Set | ||
| * | ||
| * Supports two patterns: | ||
| * - With dataSetId: Creates temporary storage context (CLI pattern) | ||
| * - With storage: Reuses existing context (library/server pattern) | ||
| */ | ||
| export type RemovePieceOptions = RemovePieceOptionsWithDataSetId | RemovePieceOptionsWithStorage | ||
|
|
||
| /** | ||
| * Remove a piece from a Data Set | ||
| * | ||
| * This function demonstrates the pattern for removing pieces via Synapse SDK. | ||
| * It supports two usage patterns: | ||
| * | ||
| * Pattern 1 - With dataSetId (typical CLI usage): | ||
| * ```typescript | ||
| * const txHash = await removePiece('baga...', { | ||
| * synapse, | ||
| * dataSetId: 42, | ||
| * logger, | ||
| * onProgress: (event) => console.log(event.type), | ||
| * waitForConfirmation: true | ||
| * }) | ||
| * ``` | ||
| * | ||
| * Pattern 2 - With existing StorageContext (library/server usage): | ||
| * ```typescript | ||
| * const { storage } = await createStorageContext(synapse, logger, {...}) | ||
| * const txHash = await removePiece('baga...', { | ||
| * synapse, | ||
| * storage, | ||
| * onProgress: (event) => console.log(event.type) | ||
| * }) | ||
| * ``` | ||
| * | ||
| * @param pieceCid - The Piece CID to remove from the Data Set | ||
| * @param options - Configuration options (dataSetId or storage context) | ||
| * @returns Transaction hash of the removal operation | ||
| * @throws Error if storage context is not bound to a Data Set | ||
| */ | ||
| export async function removePiece(pieceCid: string, options: RemovePieceOptions): Promise<`0x${string}` | string> { | ||
SgtPooki marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // Check dataSetId first | ||
| if (isRemovePieceOptionsWithDataSetId(options)) { | ||
| const { dataSetId, logger, synapse } = options | ||
| const { storage } = await createStorageContext(synapse, logger, { dataset: { useExisting: dataSetId } }) | ||
| return executeRemovePiece(pieceCid, dataSetId, storage, options) | ||
| } | ||
|
|
||
| // Handle existing storage context (library/server usage) | ||
| if (isRemovePieceOptionsWithStorage(options)) { | ||
| const dataSetId = options.storage.dataSetId | ||
| if (dataSetId == null) { | ||
| throw new Error( | ||
| 'Storage context must be bound to a Data Set before removing pieces. Use createStorageContext with dataset.useExisting to bind to a Data Set.' | ||
| ) | ||
| } | ||
| return executeRemovePiece(pieceCid, dataSetId, options.storage, options) | ||
| } | ||
|
|
||
| // Should never get here, but we need some clear error message if we do. | ||
| throw new Error('Invalid options: must provide either dataSetId or storage context') | ||
| } | ||
|
|
||
| /** | ||
| * Type guard to check if options include dataSetId | ||
| */ | ||
| function isRemovePieceOptionsWithDataSetId(options: RemovePieceOptions): options is RemovePieceOptionsWithDataSetId { | ||
| return 'dataSetId' in options | ||
| } | ||
|
|
||
| /** | ||
| * Type guard to check if options include storage context | ||
| */ | ||
| function isRemovePieceOptionsWithStorage(options: RemovePieceOptions): options is RemovePieceOptionsWithStorage { | ||
| return 'storage' in options && options.storage != null | ||
| } | ||
|
|
||
| /** | ||
| * Execute the piece removal operation | ||
| * | ||
| * This internal function handles the actual removal: | ||
| * 1. Submits transaction via storageContext.deletePiece() | ||
| * 2. Optionally waits for confirmation if requested | ||
| * 3. Emits progress events throughout the process | ||
| * | ||
| * @param pieceCid - The Piece CID to remove | ||
| * @param dataSetId - The Data Set ID (for progress events) | ||
| * @param storageContext - Storage context bound to the Data Set | ||
| * @param options - Base options including callbacks and confirmation settings | ||
| * @returns Transaction hash of the removal | ||
| */ | ||
| async function executeRemovePiece( | ||
| pieceCid: string, | ||
| dataSetId: number, | ||
| storageContext: StorageContext, | ||
| options: RemovePieceOptionsBase | ||
| ): Promise<`0x${string}` | string> { | ||
| const { onProgress, synapse, waitForConfirmation } = options | ||
|
|
||
| onProgress?.({ type: 'remove-piece:submitting', data: { pieceCid, dataSetId } }) | ||
| const txHash = await storageContext.deletePiece(pieceCid) | ||
SgtPooki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| onProgress?.({ type: 'remove-piece:submitted', data: { pieceCid, dataSetId, txHash } }) | ||
|
|
||
| let isConfirmed = false | ||
| if (waitForConfirmation === true) { | ||
| onProgress?.({ type: 'remove-piece:confirming', data: { pieceCid, dataSetId, txHash } }) | ||
| try { | ||
| await synapse.getProvider().waitForTransaction(txHash, WAIT_CONFIRMATIONS, WAIT_TIMEOUT_MS) | ||
| isConfirmed = true | ||
| } catch (error: unknown) { | ||
| // Confirmation timeout is non-fatal - transaction may still succeed | ||
| onProgress?.({ | ||
| type: 'remove-piece:confirmation-failed', | ||
| data: { pieceCid, dataSetId, txHash, message: getErrorMessage(error) as string }, | ||
SgtPooki marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }) | ||
| } | ||
| } | ||
|
|
||
| onProgress?.({ type: 'remove-piece:complete', data: { txHash, confirmed: isConfirmed } }) | ||
| return txHash | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './remove-piece.js' |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.