Skip to main content
Glama
retry-policy.test.ts7.11 kB
/** * @vitest-environment node */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { RetryPolicyType, RETRY_POLICIES, ENDPOINT_POLICIES, getRetryPolicyForEndpoint, isRetriableByPolicy, createCustomPolicy, } from '../../../utils/retry/retry-policy.js'; import { ErrorCategory } from '../../../utils/errors/categories.js'; describe('Retry Policy', () => { describe('RETRY_POLICIES', () => { it('should have all policy types defined', () => { expect(RETRY_POLICIES[RetryPolicyType.AGGRESSIVE]).toBeDefined(); expect(RETRY_POLICIES[RetryPolicyType.STANDARD]).toBeDefined(); expect(RETRY_POLICIES[RetryPolicyType.CAUTIOUS]).toBeDefined(); expect(RETRY_POLICIES[RetryPolicyType.NONE]).toBeDefined(); }); it('should have correct aggressive policy settings', () => { const policy = RETRY_POLICIES[RetryPolicyType.AGGRESSIVE]; expect(policy.maxAttempts).toBe(5); expect(policy.name).toBe('aggressive'); expect(policy.respectRetryAfter).toBe(true); expect(policy.retriableErrors).toContain(ErrorCategory.RATE_LIMIT); expect(policy.retriableErrors).toContain(ErrorCategory.NETWORK); expect(policy.retriableErrors).toContain(ErrorCategory.SERVER); expect(policy.retriableErrors).toContain(ErrorCategory.TIMEOUT); }); it('should have correct standard policy settings', () => { const policy = RETRY_POLICIES[RetryPolicyType.STANDARD]; expect(policy.maxAttempts).toBe(3); expect(policy.name).toBe('standard'); expect(policy.respectRetryAfter).toBe(true); }); it('should have correct cautious policy settings', () => { const policy = RETRY_POLICIES[RetryPolicyType.CAUTIOUS]; expect(policy.maxAttempts).toBe(1); expect(policy.name).toBe('cautious'); expect(policy.baseDelay).toBeGreaterThan(RETRY_POLICIES[RetryPolicyType.STANDARD].baseDelay); }); it('should have correct none policy settings', () => { const policy = RETRY_POLICIES[RetryPolicyType.NONE]; expect(policy.maxAttempts).toBe(0); expect(policy.name).toBe('none'); expect(policy.retriableErrors).toHaveLength(0); expect(policy.respectRetryAfter).toBe(false); }); }); describe('ENDPOINT_POLICIES', () => { it('should map read operations to appropriate policies', () => { expect(ENDPOINT_POLICIES.get('projects')).toBe(RetryPolicyType.AGGRESSIVE); expect(ENDPOINT_POLICIES.get('project_issues')).toBe(RetryPolicyType.AGGRESSIVE); expect(ENDPOINT_POLICIES.get('quality_metrics')).toBe(RetryPolicyType.STANDARD); expect(ENDPOINT_POLICIES.get('runs')).toBe(RetryPolicyType.STANDARD); }); it('should map mutation operations to none policy', () => { expect(ENDPOINT_POLICIES.get('update_metric_threshold')).toBe(RetryPolicyType.NONE); expect(ENDPOINT_POLICIES.get('update_metric_setting')).toBe(RetryPolicyType.NONE); }); }); describe('getRetryPolicyForEndpoint', () => { it('should return correct policy for known endpoints', () => { const projectsPolicy = getRetryPolicyForEndpoint('projects'); expect(projectsPolicy.name).toBe('aggressive'); const updatePolicy = getRetryPolicyForEndpoint('update_metric_threshold'); expect(updatePolicy.name).toBe('none'); }); it('should return standard policy for unknown endpoints', () => { const unknownPolicy = getRetryPolicyForEndpoint('unknown_endpoint'); expect(unknownPolicy.name).toBe('standard'); }); }); describe('isRetriableByPolicy', () => { const policy = RETRY_POLICIES[RetryPolicyType.STANDARD]; it('should return true for retriable error categories', () => { expect(isRetriableByPolicy(ErrorCategory.RATE_LIMIT, policy)).toBe(true); expect(isRetriableByPolicy(ErrorCategory.NETWORK, policy)).toBe(true); expect(isRetriableByPolicy(ErrorCategory.SERVER, policy)).toBe(true); expect(isRetriableByPolicy(ErrorCategory.TIMEOUT, policy)).toBe(true); }); it('should return false for non-retriable error categories', () => { expect(isRetriableByPolicy(ErrorCategory.AUTH, policy)).toBe(false); expect(isRetriableByPolicy(ErrorCategory.CLIENT, policy)).toBe(false); expect(isRetriableByPolicy(ErrorCategory.NOT_FOUND, policy)).toBe(false); }); it('should respect the policy retriable errors list', () => { const nonePolicy = RETRY_POLICIES[RetryPolicyType.NONE]; expect(isRetriableByPolicy(ErrorCategory.RATE_LIMIT, nonePolicy)).toBe(false); expect(isRetriableByPolicy(ErrorCategory.NETWORK, nonePolicy)).toBe(false); }); }); describe('createCustomPolicy', () => { it('should create a custom policy with overrides', () => { const customPolicy = createCustomPolicy({ maxAttempts: 10, baseDelay: 500, name: 'custom-test', }); expect(customPolicy.maxAttempts).toBe(10); expect(customPolicy.baseDelay).toBe(500); expect(customPolicy.name).toBe('custom-test'); // Should inherit other properties from standard expect(customPolicy.respectRetryAfter).toBe(true); expect(customPolicy.retriableErrors).toEqual( RETRY_POLICIES[RetryPolicyType.STANDARD].retriableErrors ); }); it('should use default name if not provided', () => { const customPolicy = createCustomPolicy({ maxAttempts: 7, }); expect(customPolicy.name).toBe('custom'); expect(customPolicy.maxAttempts).toBe(7); }); it('should allow overriding all properties', () => { const customPolicy = createCustomPolicy({ maxAttempts: 2, baseDelay: 2000, maxDelay: 10000, jitterFactor: 0.5, retriableErrors: [ErrorCategory.NETWORK], respectRetryAfter: false, name: 'minimal', }); expect(customPolicy.maxAttempts).toBe(2); expect(customPolicy.baseDelay).toBe(2000); expect(customPolicy.maxDelay).toBe(10000); expect(customPolicy.jitterFactor).toBe(0.5); expect(customPolicy.retriableErrors).toEqual([ErrorCategory.NETWORK]); expect(customPolicy.respectRetryAfter).toBe(false); expect(customPolicy.name).toBe('minimal'); }); }); describe('Environment variable configuration', () => { beforeEach(() => { // Store original env values vi.stubEnv('RETRY_MAX_ATTEMPTS', ''); vi.stubEnv('RETRY_BASE_DELAY_MS', ''); vi.stubEnv('RETRY_MAX_DELAY_MS', ''); }); it('should use environment variables when set', () => { vi.stubEnv('RETRY_MAX_ATTEMPTS', '7'); vi.stubEnv('RETRY_BASE_DELAY_MS', '2000'); vi.stubEnv('RETRY_MAX_DELAY_MS', '60000'); // Need to re-import to pick up env changes vi.resetModules(); import('../../../utils/retry/retry-policy.js').then((module) => { const policy = module.RETRY_POLICIES[module.RetryPolicyType.STANDARD]; expect(policy.maxAttempts).toBe(7); expect(policy.baseDelay).toBe(2000); expect(policy.maxDelay).toBe(60000); }); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sapientpants/deepsource-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server