{"id":16157534,"url":"https://github.com/ceynri/request-hedging","last_synced_at":"2025-10-07T12:28:23.024Z","repository":{"id":223077054,"uuid":"754715949","full_name":"ceynri/request-hedging","owner":"ceynri","description":"Request hedging policy in the frontend.","archived":false,"fork":false,"pushed_at":"2024-04-09T04:20:55.000Z","size":57,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-12T02:51:58.492Z","etag":null,"topics":["frontend","grpc","hedging","npm","pnpm","request","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ceynri.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-08T16:25:49.000Z","updated_at":"2024-02-27T07:00:58.000Z","dependencies_parsed_at":"2024-11-02T04:22:32.186Z","dependency_job_id":"e2193691-519f-4b5b-9a9e-34729658f3f1","html_url":"https://github.com/ceynri/request-hedging","commit_stats":null,"previous_names":["ceynri/request-hedging"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ceynri/request-hedging","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceynri%2Frequest-hedging","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceynri%2Frequest-hedging/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceynri%2Frequest-hedging/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceynri%2Frequest-hedging/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ceynri","download_url":"https://codeload.github.com/ceynri/request-hedging/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceynri%2Frequest-hedging/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260754202,"owners_count":23057726,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frontend","grpc","hedging","npm","pnpm","request","typescript"],"created_at":"2024-10-10T01:49:48.209Z","updated_at":"2025-10-07T12:28:18.002Z","avatar_url":"https://github.com/ceynri.png","language":"TypeScript","readme":"# request-hedging\n\nRequest hedging policy in the frontend.\n\nNot requestor, just hedging policy logic implementation.\n\n## Introduction\n\nHedging policy can be regarded as an aggressive retry policy. A complete request may send multiple identical requests until one of them returns successfully. We don't need to wait for the previous request to time out before sending a new hedging request, which makes the hedging policy have a better optimization effect for long-tail requests.\n\n![example](https://fastly.jsdelivr.net/gh/ceynri/assets@main/images/17126364119081712636411004.png)\n\n\u003e Hedging policy in the backend:\n\u003e\n\u003e - [gRPC Retry Design](https://github.com/grpc/proposal/blob/master/A6-client-retries.md#hedging-policy)\n\u003e - [gRPC Request Hedging](https://grpc.io/docs/guides/request-hedging/)\n\u003e - [The Tail At Scale](https://research.google/pubs/pub40801/)\n\n## Getting started\n\n```sh\nnpm install request-hedging\n# or yarn/pnpm...\n```\n\n## Use Cases\n\nSingle request hedging:\n\n```ts\nimport { hedging } from 'request-hedging';\n\nconst result = await hedging(() =\u003e fetch('https://example.com/apis/getData'), {\n  maxAttempts: 3, // Up to three times attempted (not required)\n});\n```\n\nMultiple requests hedging：\n\n```ts\nimport { hedging } from 'request-hedging';\n\nconst result = await hedging([\n  () =\u003e fetch('https://example.com/apis/getData'),\n  () =\u003e fetch('https://example.com/backup-apis/getData'),\n]);\n```\n\nUse `useHedging`：\n\n```ts\nimport { useHedging } from 'request-hedging';\n\nconst hedging = useHedging({\n  maxAttempts: 3,\n  hedgingDelay: 500,\n});\n\nconst result1 = await hedging(() =\u003e fetch('https://example.com/apis/getData'));\n\nconst result2 = await hedging([\n  () =\u003e fetch('https://example.com/apis/getData'),\n  () =\u003e fetch('https://example.com/backup-apis/getData'),\n], { maxAttempts: 2 });\n```\n\n## Options\n\n| name           | type                                       | default value                      |\n| -------------- | ------------------------------------------ | ---------------------------------- |\n| maxAttempts    | `number`                                   | `Math.max(this.targets.length, 2)` |\n| hedgingDelay   | `number` (ms)                              | `1000`                             |\n| timeout        | `number` (ms)                              | `Infinity`                         |\n| retryableError | `boolean \\| ((error: unknown) =\u003e boolean)` | `true`                             |\n\n---\n\n## Local Dev\n\n- node \u003e= 18\n- pnpm \u003e= 9\n\n```sh\n# request-hedging repo\npnpm i\npnpm dev\n\n# Another repo\npnpm link /path/to/request-hedging\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fceynri%2Frequest-hedging","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fceynri%2Frequest-hedging","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fceynri%2Frequest-hedging/lists"}