Skip to content

Commit cce43d2

Browse files
committed
Add coverage support, SECURITY.md, article outline, and coverage badge
- Install @vitest/coverage-v8 with text + lcov reporters - Add vitest.config.ts with V8 coverage configuration - Add coverage badge to README (94% statement coverage) - Create SECURITY.md with responsible disclosure process - Create docs/article-outline.md for technical article draft
1 parent e504a36 commit cce43d2

6 files changed

Lines changed: 367 additions & 4 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[![npm version](https://img.shields.io/npm/v/@rootvector/smart-retry.svg)](https://www.npmjs.com/package/@rootvector/smart-retry)
44
[![npm downloads](https://img.shields.io/npm/dm/@rootvector/smart-retry.svg)](https://www.npmjs.com/package/@rootvector/smart-retry)
55
[![CI](https://github.com/rootvector2/SmartRetry/actions/workflows/ci.yml/badge.svg)](https://github.com/rootvector2/SmartRetry/actions)
6+
[![coverage](https://img.shields.io/badge/coverage-94%25-brightgreen)](https://github.com/rootvector2/SmartRetry)
67
[![License](https://img.shields.io/npm/l/@rootvector/smart-retry.svg)](LICENSE)
78

89
Async functions fail. Networks drop, servers return 500s, rate limits kick in. SmartRetry wraps any async function with configurable retry logic — exponential backoff, jitter, global timeouts, and cancellation via `AbortSignal` — so you don't have to write that boilerplate again.

SECURITY.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Security Policy
2+
3+
## Reporting a Vulnerability
4+
5+
If you discover a security vulnerability in SmartRetry, please report it responsibly.
6+
7+
**Do not open a public GitHub issue for security vulnerabilities.**
8+
9+
### Contact
10+
11+
Email: **dxbnaveed.k@gmail.com**
12+
13+
Subject line: `[SECURITY] SmartRetry — <brief description>`
14+
15+
### What to Include
16+
17+
- Description of the vulnerability
18+
- Steps to reproduce
19+
- Potential impact
20+
- Suggested fix (if any)
21+
22+
### Disclosure Process
23+
24+
1. Report the vulnerability via email.
25+
2. You will receive an acknowledgment within 48 hours.
26+
3. A fix will be developed and tested privately.
27+
4. A patch release will be published with a security advisory.
28+
5. Public disclosure after the fix is available.
29+
30+
### Scope
31+
32+
This policy covers the `@rootvector/smart-retry` npm package and its source code at [github.com/rootvector2/SmartRetry](https://github.com/rootvector2/SmartRetry).
33+
34+
Thank you for helping keep SmartRetry secure.

docs/article-outline.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Implementing a Correct Retry Mechanism in TypeScript (With Backoff, Jitter & AbortSignal)
2+
3+
## Outline
4+
5+
### 1. Why Naive Retry Is Dangerous
6+
7+
- The instinct to "just retry" masks real failure modes
8+
- Unbounded retries amplify load on failing services
9+
- Silent retry loops hide bugs and delay incident detection
10+
11+
### 2. The Thundering Herd Problem
12+
13+
- What happens when thousands of clients retry simultaneously
14+
- Fixed-delay retries create synchronized spikes
15+
- Real-world examples: AWS outages, API rate limit cascades
16+
17+
### 3. Why Jitter Matters
18+
19+
- Exponential backoff alone still creates clusters
20+
- Full jitter vs. equal jitter vs. decorrelated jitter
21+
- Mathematical intuition: spreading retry attempts across time
22+
- Reference: AWS Architecture Blog on exponential backoff
23+
24+
### 4. Timeout: Global vs. Per-Attempt
25+
26+
- Per-attempt timeout: each call gets N seconds (incomplete picture)
27+
- Global timeout: total wall-clock budget across all attempts
28+
- Why global timeout is the correct default for production systems
29+
- Edge case: what if the last retry starts just before timeout?
30+
31+
### 5. AbortSignal Correctness
32+
33+
- Why cancellation is not optional in production async code
34+
- Common mistakes: not cleaning up listeners, ignoring abort during sleep
35+
- Correct pattern: wiring AbortSignal through retry loop and delay
36+
- Interaction between AbortSignal and global timeout
37+
38+
### 6. Common Bugs in Retry Loops
39+
40+
- Retrying non-retryable errors (400, 401, 403, 404)
41+
- Wrapping all errors in a generic "retry failed" error
42+
- Off-by-one: `maxRetries` vs. total attempts
43+
- Not clamping delay to remaining timeout budget
44+
- Leaking timers on abort
45+
46+
### 7. Introducing SmartRetry
47+
48+
- Design goals: correctness, predictability, zero dependencies
49+
- Default retry policy: network errors, 429, 5xx — stop on 4xx
50+
- Full jitter by default
51+
- Global timeout with proper delay clamping
52+
- AbortSignal support with clean teardown
53+
- ESM + CJS dual build, fully typed
54+
55+
### 8. Example Usage
56+
57+
- Basic: wrapping a fetch call
58+
- Advanced: custom retry predicate with structured logging
59+
- Cancellation: AbortController with timeout fallback
60+
61+
### 9. Benchmarks (Future)
62+
63+
- Retry storm simulation: SmartRetry vs. naive loops
64+
- Jitter distribution visualization
65+
- Memory and timer cleanup validation
66+
67+
---
68+
69+
**Target platforms:** Dev.to, Hashnode, Medium, personal blog
70+
71+
**Estimated length:** 2,500–3,500 words
72+
73+
**Goal:** Establish authority on retry correctness; drive organic traffic to the npm package.

0 commit comments

Comments
 (0)