AgentSkillsCN

replit-reliability-patterns

实施 Replit 可靠性模式,包括熔断器、幂等与优雅降级。 在构建容错 Replit 集成、实施重试策略或为生产 Replit 服务增加韧性时使用。 可通过诸如“replit 可靠性”、“replit 熔断器”、“replit 幂等”、“replit 韧性”、“replit 回退”、“replit 隔舱”等短语触发。

SKILL.md
--- frontmatter
name: replit-reliability-patterns
description: |
  Implement Replit reliability patterns including circuit breakers, idempotency, and graceful degradation.
  Use when building fault-tolerant Replit integrations, implementing retry strategies,
  or adding resilience to production Replit services.
  Trigger with phrases like "replit reliability", "replit circuit breaker",
  "replit idempotent", "replit resilience", "replit fallback", "replit bulkhead".
allowed-tools: Read, Write, Edit
version: 1.0.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>

Replit Reliability Patterns

Overview

Production-grade reliability patterns for Replit integrations.

Prerequisites

  • Understanding of circuit breaker pattern
  • opossum or similar library installed
  • Queue infrastructure for DLQ
  • Caching layer for fallbacks

Circuit Breaker

typescript
import CircuitBreaker from 'opossum';

const replitBreaker = new CircuitBreaker(
  async (operation: () => Promise<any>) => operation(),
  {
    timeout: 30000,
    errorThresholdPercentage: 50,
    resetTimeout: 30000,
    volumeThreshold: 10,
  }
);

// Events
replitBreaker.on('open', () => {
  console.warn('Replit circuit OPEN - requests failing fast');
  alertOps('Replit circuit breaker opened');
});

replitBreaker.on('halfOpen', () => {
  console.info('Replit circuit HALF-OPEN - testing recovery');
});

replitBreaker.on('close', () => {
  console.info('Replit circuit CLOSED - normal operation');
});

// Usage
async function safeReplitCall<T>(fn: () => Promise<T>): Promise<T> {
  return replitBreaker.fire(fn);
}

Idempotency Keys

typescript
import { v4 as uuidv4 } from 'uuid';
import crypto from 'crypto';

// Generate deterministic idempotency key from input
function generateIdempotencyKey(
  operation: string,
  params: Record<string, any>
): string {
  const data = JSON.stringify({ operation, params });
  return crypto.createHash('sha256').update(data).digest('hex');
}

// Or use random key with storage
class IdempotencyManager {
  private store: Map<string, { key: string; expiresAt: Date }> = new Map();

  getOrCreate(operationId: string): string {
    const existing = this.store.get(operationId);
    if (existing && existing.expiresAt > new Date()) {
      return existing.key;
    }

    const key = uuidv4();
    this.store.set(operationId, {
      key,
      expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
    });
    return key;
  }
}

Bulkhead Pattern

typescript
import PQueue from 'p-queue';

// Separate queues for different operations
const replitQueues = {
  critical: new PQueue({ concurrency: 10 }),
  normal: new PQueue({ concurrency: 5 }),
  bulk: new PQueue({ concurrency: 2 }),
};

async function prioritizedReplitCall<T>(
  priority: 'critical' | 'normal' | 'bulk',
  fn: () => Promise<T>
): Promise<T> {
  return replitQueues[priority].add(fn);
}

// Usage
await prioritizedReplitCall('critical', () =>
  replitClient.processPayment(order)
);

await prioritizedReplitCall('bulk', () =>
  replitClient.syncCatalog(products)
);

Timeout Hierarchy

typescript
const TIMEOUT_CONFIG = {
  connect: 5000,      // Initial connection
  request: 30000,     // Standard requests
  upload: 120000,     // File uploads
  longPoll: 300000,   // Webhook long-polling
};

async function timedoutReplitCall<T>(
  operation: 'connect' | 'request' | 'upload' | 'longPoll',
  fn: () => Promise<T>
): Promise<T> {
  const timeout = TIMEOUT_CONFIG[operation];

  return Promise.race([
    fn(),
    new Promise<never>((_, reject) =>
      setTimeout(() => reject(new Error(`Replit ${operation} timeout`)), timeout)
    ),
  ]);
}

Graceful Degradation

typescript
interface ReplitFallback {
  enabled: boolean;
  data: any;
  staleness: 'fresh' | 'stale' | 'very_stale';
}

async function withReplitFallback<T>(
  fn: () => Promise<T>,
  fallbackFn: () => Promise<T>
): Promise<{ data: T; fallback: boolean }> {
  try {
    const data = await fn();
    // Update cache for future fallback
    await updateFallbackCache(data);
    return { data, fallback: false };
  } catch (error) {
    console.warn('Replit failed, using fallback:', error.message);
    const data = await fallbackFn();
    return { data, fallback: true };
  }
}

Dead Letter Queue

typescript
interface DeadLetterEntry {
  id: string;
  operation: string;
  payload: any;
  error: string;
  attempts: number;
  lastAttempt: Date;
}

class ReplitDeadLetterQueue {
  private queue: DeadLetterEntry[] = [];

  add(entry: Omit<DeadLetterEntry, 'id' | 'lastAttempt'>): void {
    this.queue.push({
      ...entry,
      id: uuidv4(),
      lastAttempt: new Date(),
    });
  }

  async processOne(): Promise<boolean> {
    const entry = this.queue.shift();
    if (!entry) return false;

    try {
      await replitClient[entry.operation](entry.payload);
      console.log(`DLQ: Successfully reprocessed ${entry.id}`);
      return true;
    } catch (error) {
      entry.attempts++;
      entry.lastAttempt = new Date();

      if (entry.attempts < 5) {
        this.queue.push(entry);
      } else {
        console.error(`DLQ: Giving up on ${entry.id} after 5 attempts`);
        await alertOnPermanentFailure(entry);
      }
      return false;
    }
  }
}

Health Check with Degraded State

typescript
type HealthStatus = 'healthy' | 'degraded' | 'unhealthy';

async function replitHealthCheck(): Promise<{
  status: HealthStatus;
  details: Record<string, any>;
}> {
  const checks = {
    api: await checkApiConnectivity(),
    circuitBreaker: replitBreaker.stats(),
    dlqSize: deadLetterQueue.size(),
  };

  const status: HealthStatus =
    !checks.api.connected ? 'unhealthy' :
    checks.circuitBreaker.state === 'open' ? 'degraded' :
    checks.dlqSize > 100 ? 'degraded' :
    'healthy';

  return { status, details: checks };
}

Instructions

Step 1: Implement Circuit Breaker

Wrap Replit calls with circuit breaker.

Step 2: Add Idempotency Keys

Generate deterministic keys for operations.

Step 3: Configure Bulkheads

Separate queues for different priorities.

Step 4: Set Up Dead Letter Queue

Handle permanent failures gracefully.

Output

  • Circuit breaker protecting Replit calls
  • Idempotency preventing duplicates
  • Bulkhead isolation implemented
  • DLQ for failed operations

Error Handling

IssueCauseSolution
Circuit stays openThreshold too lowAdjust error percentage
Duplicate operationsMissing idempotencyAdd idempotency key
Queue fullRate too highIncrease concurrency
DLQ growingPersistent failuresInvestigate root cause

Examples

Quick Circuit Check

typescript
const state = replitBreaker.stats().state;
console.log('Replit circuit:', state);

Resources

Next Steps

For policy enforcement, see replit-policy-guardrails.