or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index-management.mdindex.mdlisting.mdreading.mdremoval.mdutilities.mdverification.mdwriting.md
tile.json

removal.mddocs/

Removal Operations

Operations for removing cached data, either by key or by content hash, including full cache cleanup and maintenance.

Capabilities

Remove Entry by Key

Removes a cache entry by its key, including both the index entry and associated content (if not referenced by other entries).

/**
 * Removes cache entry by key
 * @param {string} cache - Path to cache directory
 * @param {string} key - Cache key to remove
 * @param {object} opts - Options object
 * @param {boolean} [opts.removeFully=false] - Remove entire index bucket file
 * @returns {Promise<void>} Promise that resolves when removal is complete
 */
function rm.entry(cache, key, opts);

// Alias - rm() is equivalent to rm.entry()
function rm(cache, key, opts);

Usage Examples:

const cacache = require('cacache');

// Remove specific entry
await cacache.rm.entry('./cache', 'my-key');
console.log('Entry removed');

// Alternative syntax
await cacache.rm('./cache', 'my-key');

// Full removal (removes entire bucket file)
await cacache.rm.entry('./cache', 'my-key', { removeFully: true });

// Remove multiple entries
const keysToRemove = ['key1', 'key2', 'key3'];
await Promise.all(keysToRemove.map(key => 
  cacache.rm.entry('./cache', key)
));

Remove Content by Hash

Removes cached content by its integrity hash. This removes the actual content file but leaves any index entries that reference it.

/**
 * Removes cached content by integrity hash
 * @param {string} cache - Path to cache directory
 * @param {string} integrity - Content integrity hash (SRI format)
 * @returns {Promise<void>} Promise that resolves when removal is complete
 */
function rm.content(cache, integrity);

Usage Examples:

// Remove content by hash
await cacache.rm.content('./cache', 'sha512-abc123...');
console.log('Content removed');

// Remove content after getting its hash
const info = await cacache.get.info('./cache', 'my-key');
if (info) {
  await cacache.rm.content('./cache', info.integrity);
  console.log('Content removed, but index entry remains');
}

// Remove multiple content files
const integritiesToRemove = [
  'sha512-abc123...',
  'sha512-def456...',
  'sha512-ghi789...'
];
await Promise.all(integritiesToRemove.map(integrity =>
  cacache.rm.content('./cache', integrity)
));

Remove All Cache Contents

Removes the entire cache contents, including all index files and content files. This is equivalent to deleting the entire cache directory contents.

/**
 * Removes entire cache contents
 * @param {string} cache - Path to cache directory
 * @returns {Promise<void>} Promise that resolves when removal is complete
 */
function rm.all(cache);

Usage Examples:

// Clear entire cache
await cacache.rm.all('./cache');
console.log('Cache completely cleared');

// Clear cache with error handling
try {
  await cacache.rm.all('./cache');
  console.log('Cache cleared successfully');
} catch (error) {
  if (error.code === 'ENOENT') {
    console.log('Cache directory does not exist');
  } else {
    console.error('Failed to clear cache:', error);
  }
}

// Clear and recreate cache directory
await cacache.rm.all('./cache');
await cacache.verify('./cache'); // This will recreate directory structure

Advanced Removal Patterns

Conditional Removal

Remove entries based on conditions:

// Remove entries older than 7 days
const entries = await cacache.ls('./cache');
const weekAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);

for (const [key, entry] of Object.entries(entries)) {
  if (entry.time < weekAgo) {
    await cacache.rm.entry('./cache', key);
    console.log(`Removed old entry: ${key}`);
  }
}

Safe Content Removal

Remove content only if not referenced by any entries:

async function safeRemoveContent(cache, integrity) {
  // Check if any entries reference this content
  const entries = await cacache.ls(cache);
  const isReferenced = Object.values(entries).some(
    entry => entry.integrity === integrity
  );
  
  if (!isReferenced) {
    await cacache.rm.content(cache, integrity);
    console.log('Content safely removed');
  } else {
    console.log('Content still referenced by entries, skipping removal');
  }
}

await safeRemoveContent('./cache', 'sha512-abc123...');

Cleanup by Pattern

Remove entries matching specific patterns:

// Remove all entries starting with "temp-"
const entries = await cacache.ls('./cache');
const tempKeys = Object.keys(entries).filter(key => key.startsWith('temp-'));

await Promise.all(tempKeys.map(key => 
  cacache.rm.entry('./cache', key)
));
console.log(`Removed ${tempKeys.length} temporary entries`);

// Remove entries with specific metadata
const entries = await cacache.ls('./cache');
const expiredKeys = Object.entries(entries)
  .filter(([key, entry]) => 
    entry.metadata && entry.metadata.expires && 
    entry.metadata.expires < Date.now()
  )
  .map(([key]) => key);

await Promise.all(expiredKeys.map(key =>
  cacache.rm.entry('./cache', key)
));
console.log(`Removed ${expiredKeys.length} expired entries`);

Batch Removal with Error Handling

Remove multiple items with individual error handling:

async function batchRemove(cache, keys) {
  const results = await Promise.allSettled(
    keys.map(async (key) => {
      try {
        await cacache.rm.entry(cache, key);
        return { key, status: 'removed' };
      } catch (error) {
        return { key, status: 'error', error: error.message };
      }
    })
  );
  
  const removed = results.filter(r => r.value?.status === 'removed').length;
  const errors = results.filter(r => r.value?.status === 'error').length;
  
  console.log(`Removed: ${removed}, Errors: ${errors}`);
  return results;
}

const keysToRemove = ['key1', 'key2', 'nonexistent-key'];
const results = await batchRemove('./cache', keysToRemove);

Cache Maintenance

Orphaned Content Cleanup

Remove content files that are no longer referenced by any index entries:

async function cleanupOrphanedContent(cache) {
  // Get all referenced content hashes
  const entries = await cacache.ls(cache);
  const referencedHashes = new Set(
    Object.values(entries).map(entry => entry.integrity)
  );
  
  // This would require additional logic to scan content directory
  // In practice, use cacache.verify() for comprehensive cleanup
  console.log(`Found ${referencedHashes.size} referenced content files`);
  
  // Better approach: use verify for comprehensive cleanup
  const stats = await cacache.verify(cache);
  console.log(`Cleanup stats:`, stats);
}

Selective Cleanup

Clean cache based on size limits:

async function cleanupBySize(cache, maxSizeBytes) {
  const entries = await cacache.ls(cache);
  
  // Sort by access time (oldest first)
  const sortedEntries = Object.entries(entries)
    .sort(([,a], [,b]) => a.time - b.time);
  
  let totalSize = sortedEntries.reduce((sum, [,entry]) => sum + entry.size, 0);
  
  for (const [key, entry] of sortedEntries) {
    if (totalSize <= maxSizeBytes) break;
    
    await cacache.rm.entry(cache, key);
    totalSize -= entry.size;
    console.log(`Removed ${key} (${entry.size} bytes)`);
  }
  
  console.log(`Cache size reduced to ${totalSize} bytes`);
}

// Keep cache under 100MB
await cleanupBySize('./cache', 100 * 1024 * 1024);

Error Handling

Removal operations may encounter various errors:

try {
  await cacache.rm.entry('./cache', 'some-key');
} catch (error) {
  switch (error.code) {
    case 'ENOENT':
      console.log('Entry or cache directory does not exist');
      break;
    case 'EACCES':
      console.error('Permission denied');
      break;
    case 'EBUSY':
      console.error('File is busy or locked');
      break;
    default:
      console.error('Unexpected error:', error);
  }
}

Important Notes

Removal Behavior

  • rm.entry() marks entries as deleted in the index (appends null integrity)
  • Physical cleanup happens during verify() operations
  • rm.content() immediately removes content files
  • rm.all() removes entire cache directory contents

Concurrency Safety

  • All removal operations are safe for concurrent access
  • Multiple processes can safely remove different entries simultaneously
  • Index operations use atomic append-only writes

Memory Management

  • Removal operations automatically clear related memoization cache entries
  • Large batch removals may benefit from periodic clearMemoized() calls