Exponential backoff retry logic
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(lint): rename constructors to v and resolve E332/E331/E410 across packages

Rename create/make to v in rpmsg, error, proxy, auth, version, and
other modules. Fix doc style issues in error.mli, requests.mli, and
expect_continue.mli. Update all callers.

+74 -79
+74 -79
test/test.ml
··· 1 1 (* Config tests *) 2 2 3 - let test_default_config () = 3 + let default_config () = 4 4 let config = Retry.default_config in 5 5 Alcotest.(check int) "max_retries" 3 config.max_retries; 6 6 Alcotest.(check (float 0.01)) "backoff_factor" 0.3 config.backoff_factor; 7 7 Alcotest.(check (float 0.01)) "backoff_max" 120.0 config.backoff_max; 8 8 Alcotest.(check bool) "jitter" true config.jitter 9 9 10 - let test_config_defaults () = 10 + let config_defaults () = 11 11 let config = Retry.config () in 12 12 Alcotest.(check int) "max_retries" 3 config.max_retries; 13 13 Alcotest.(check (float 0.01)) "backoff_factor" 0.3 config.backoff_factor; 14 14 Alcotest.(check (float 0.01)) "backoff_max" 120.0 config.backoff_max; 15 15 Alcotest.(check bool) "jitter" true config.jitter 16 16 17 - let test_config_custom () = 17 + let config_custom () = 18 18 let config = 19 19 Retry.config ~max_retries:10 ~backoff_factor:1.0 ~backoff_max:60.0 20 20 ~jitter:false () ··· 24 24 Alcotest.(check (float 0.01)) "backoff_max" 60.0 config.backoff_max; 25 25 Alcotest.(check bool) "jitter" false config.jitter 26 26 27 - let test_config_partial () = 27 + let config_partial () = 28 28 let config = Retry.config ~max_retries:5 ~jitter:false () in 29 29 Alcotest.(check int) "max_retries" 5 config.max_retries; 30 30 Alcotest.(check (float 0.01)) "backoff_factor" 0.3 config.backoff_factor; 31 31 Alcotest.(check (float 0.01)) "backoff_max" 120.0 config.backoff_max; 32 32 Alcotest.(check bool) "jitter" false config.jitter 33 33 34 - let test_pp_config () = 34 + let pp_config () = 35 35 let config = 36 36 Retry.config ~max_retries:5 ~backoff_factor:0.5 ~backoff_max:30.0 37 37 ~jitter:true () ··· 80 80 let backoff_test_vectors_no_cap = 81 81 [ (0, 1.0); (1, 2.0); (2, 4.0); (3, 8.0); (4, 16.0); (5, 32.0); (10, 1024.0) ] 82 82 83 - let test_backoff_test_vectors () = 83 + let backoff_test_vectors () = 84 84 let config = 85 85 Retry.config ~backoff_factor:1.0 ~backoff_max:10000.0 ~jitter:false () 86 86 in ··· 120 120 (10, 120.0); 121 121 ] 122 122 123 - let test_backoff_default_config_vectors () = 123 + let backoff_default_config_vectors () = 124 124 let config = 125 125 Retry.config ~backoff_factor:0.3 ~backoff_max:120.0 ~jitter:false () 126 126 in ··· 155 155 (8, 10.0); 156 156 ] 157 157 158 - let test_backoff_aws_style () = 158 + let backoff_aws_style () = 159 159 let config = 160 160 Retry.config ~backoff_factor:0.1 ~backoff_max:10.0 ~jitter:false () 161 161 in ··· 181 181 let backoff_test_vectors_gcp_style = 182 182 [ (0, 1.0); (1, 2.0); (2, 4.0); (3, 8.0); (4, 16.0); (5, 32.0); (6, 32.0) ] 183 183 184 - let test_backoff_gcp_style () = 184 + let backoff_gcp_style () = 185 185 let config = 186 186 Retry.config ~backoff_factor:1.0 ~backoff_max:32.0 ~jitter:false () 187 187 in ··· 193 193 expected delay) 194 194 backoff_test_vectors_gcp_style 195 195 196 - let test_backoff_no_jitter () = 196 + let backoff_no_jitter () = 197 197 let config = 198 198 Retry.config ~backoff_factor:1.0 ~backoff_max:1000.0 ~jitter:false () 199 199 in ··· 207 207 let delay3 = Retry.calculate_backoff ~config ~attempt:3 in 208 208 Alcotest.(check (float 0.01)) "attempt 3" 8.0 delay3 209 209 210 - let test_backoff_exponential () = 210 + let backoff_exponential () = 211 211 let config = 212 212 Retry.config ~backoff_factor:0.5 ~backoff_max:1000.0 ~jitter:false () 213 213 in ··· 221 221 let delay5 = Retry.calculate_backoff ~config ~attempt:5 in 222 222 Alcotest.(check (float 0.01)) "attempt 5" 16.0 delay5 223 223 224 - let test_backoff_capped () = 224 + let backoff_capped () = 225 225 let config = 226 226 Retry.config ~backoff_factor:1.0 ~backoff_max:5.0 ~jitter:false () 227 227 in ··· 238 238 let delay10 = Retry.calculate_backoff ~config ~attempt:10 in 239 239 Alcotest.(check (float 0.01)) "attempt 10 capped" 5.0 delay10 240 240 241 - let test_backoff_with_jitter () = 241 + let backoff_with_jitter () = 242 242 let config = 243 243 Retry.config ~backoff_factor:1.0 ~backoff_max:1000.0 ~jitter:true () 244 244 in ··· 253 253 Alcotest.(check bool) "delay < 4.0" true (delay < 4.0)) 254 254 delays 255 255 256 - let test_backoff_zero_factor () = 256 + let backoff_zero_factor () = 257 257 let config = 258 258 Retry.config ~backoff_factor:0.0 ~backoff_max:1000.0 ~jitter:false () 259 259 in 260 260 let delay = Retry.calculate_backoff ~config ~attempt:5 in 261 261 Alcotest.(check (float 0.01)) "zero factor gives zero delay" 0.0 delay 262 262 263 - let test_backoff_attempt_zero () = 263 + let backoff_attempt_zero () = 264 264 let config = 265 265 Retry.config ~backoff_factor:1.0 ~backoff_max:1000.0 ~jitter:false () 266 266 in ··· 270 270 271 271 (* with_retry tests *) 272 272 273 - let test_success_first_try () = 273 + let success_first_try () = 274 274 Eio_main.run @@ fun env -> 275 275 let clock = Eio.Stdenv.clock env in 276 276 let config = Retry.config ~max_retries:3 () in ··· 285 285 Alcotest.(check string) "result" "success" result; 286 286 Alcotest.(check int) "called once" 1 !calls 287 287 288 - let test_retry_then_success () = 288 + let retry_then_success () = 289 289 Eio_main.run @@ fun env -> 290 290 let clock = Eio.Stdenv.clock env in 291 291 let config = ··· 303 303 Alcotest.(check string) "result" "success" result; 304 304 Alcotest.(check int) "called 3 times" 3 !calls 305 305 306 - let test_exhaust_retries () = 306 + let exhaust_retries () = 307 307 Eio_main.run @@ fun env -> 308 308 let clock = Eio.Stdenv.clock env in 309 309 let config = ··· 325 325 Alcotest.(check bool) "raised" true raised; 326 326 Alcotest.(check int) "called max+1 times" 3 !calls 327 327 328 - let test_should_retry_false () = 328 + let should_retry_false () = 329 329 Eio_main.run @@ fun env -> 330 330 let clock = Eio.Stdenv.clock env in 331 331 let config = ··· 347 347 Alcotest.(check bool) "raised" true raised; 348 348 Alcotest.(check int) "called only once (no retry)" 1 !calls 349 349 350 - let test_selective_retry () = 350 + let selective_retry () = 351 351 Eio_main.run @@ fun env -> 352 352 let clock = Eio.Stdenv.clock env in 353 353 let config = ··· 367 367 Alcotest.(check string) "result" "success" result; 368 368 Alcotest.(check int) "called 3 times" 3 !calls 369 369 370 - let test_selective_retry_permanent_failure () = 370 + let selective_retry_permanent_failure () = 371 371 Eio_main.run @@ fun env -> 372 372 let clock = Eio.Stdenv.clock env in 373 373 let config = ··· 391 391 Alcotest.(check bool) "raised permanent" true raised; 392 392 Alcotest.(check int) "called only once" 1 !calls 393 393 394 - let test_zero_retries () = 394 + let zero_retries () = 395 395 Eio_main.run @@ fun env -> 396 396 let clock = Eio.Stdenv.clock env in 397 397 let config = ··· 413 413 Alcotest.(check bool) "raised" true raised; 414 414 Alcotest.(check int) "called only once (no retries)" 1 !calls 415 415 416 - let test_success_on_last_attempt () = 416 + let success_on_last_attempt () = 417 417 Eio_main.run @@ fun env -> 418 418 let clock = Eio.Stdenv.clock env in 419 419 let config = ··· 431 431 Alcotest.(check string) "result" "success" result; 432 432 Alcotest.(check int) "called 4 times (1 + 3 retries)" 4 !calls 433 433 434 - let test_different_exception_types () = 434 + let different_exception_types () = 435 435 Eio_main.run @@ fun env -> 436 436 let clock = Eio.Stdenv.clock env in 437 437 let config = ··· 456 456 Alcotest.(check string) "result" "success" result; 457 457 Alcotest.(check int) "called 4 times" 4 !calls 458 458 459 - let test_non_retryable_exception () = 459 + let non_retryable_exception () = 460 460 Eio_main.run @@ fun env -> 461 461 let clock = Eio.Stdenv.clock env in 462 462 let config = ··· 479 479 480 480 (* with_retry_result tests *) 481 481 482 - let test_result_success_first_try () = 482 + let result_success_first_try () = 483 483 Eio_main.run @@ fun env -> 484 484 let clock = Eio.Stdenv.clock env in 485 485 let config = Retry.config ~max_retries:3 () in ··· 494 494 Alcotest.(check (result string string)) "result" (Ok "success") result; 495 495 Alcotest.(check int) "called once" 1 !calls 496 496 497 - let test_result_retry () = 497 + let result_retry () = 498 498 Eio_main.run @@ fun env -> 499 499 let clock = Eio.Stdenv.clock env in 500 500 let config = ··· 511 511 Alcotest.(check (result string string)) "result" (Ok "success") result; 512 512 Alcotest.(check int) "called 2 times" 2 !calls 513 513 514 - let test_result_exhaust_retries () = 514 + let result_exhaust_retries () = 515 515 Eio_main.run @@ fun env -> 516 516 let clock = Eio.Stdenv.clock env in 517 517 let config = ··· 528 528 Alcotest.(check (result string string)) "result" (Error "always fail") result; 529 529 Alcotest.(check int) "called max+1 times" 3 !calls 530 530 531 - let test_result_should_retry_false () = 531 + let result_should_retry_false () = 532 532 Eio_main.run @@ fun env -> 533 533 let clock = Eio.Stdenv.clock env in 534 534 let config = ··· 545 545 Alcotest.(check (result string string)) "result" (Error "fail") result; 546 546 Alcotest.(check int) "called only once" 1 !calls 547 547 548 - let test_result_selective_retry () = 548 + let result_selective_retry () = 549 549 Eio_main.run @@ fun env -> 550 550 let clock = Eio.Stdenv.clock env in 551 551 let config = ··· 561 561 Alcotest.(check (result string string)) "result" (Ok "success") result; 562 562 Alcotest.(check int) "called 3 times" 3 !calls 563 563 564 - let test_result_permanent_error () = 564 + let result_permanent_error () = 565 565 Eio_main.run @@ fun env -> 566 566 let clock = Eio.Stdenv.clock env in 567 567 let config = ··· 577 577 Alcotest.(check (result string string)) "result" (Error "permanent") result; 578 578 Alcotest.(check int) "called only once" 1 !calls 579 579 580 - let test_result_zero_retries () = 580 + let result_zero_retries () = 581 581 Eio_main.run @@ fun env -> 582 582 let clock = Eio.Stdenv.clock env in 583 583 let config = ··· 594 594 Alcotest.(check (result string string)) "result" (Error "fail") result; 595 595 Alcotest.(check int) "called only once" 1 !calls 596 596 597 - let test_result_success_on_last_attempt () = 597 + let result_success_on_last_attempt () = 598 598 Eio_main.run @@ fun env -> 599 599 let clock = Eio.Stdenv.clock env in 600 600 let config = ··· 625 625 626 626 let error_kind_testable = Alcotest.testable pp_error_kind error_kind_equal 627 627 628 - let test_result_typed_errors () = 628 + let result_typed_errors () = 629 629 Eio_main.run @@ fun env -> 630 630 let clock = Eio.Stdenv.clock env in 631 631 let config = ··· 650 650 "result" (Ok "success") result; 651 651 Alcotest.(check int) "called 4 times" 4 !calls 652 652 653 - let test_result_typed_permanent_error () = 653 + let result_typed_permanent_error () = 654 654 Eio_main.run @@ fun env -> 655 655 let clock = Eio.Stdenv.clock env in 656 656 let config = ··· 671 671 "result" (Error Permanent) result; 672 672 Alcotest.(check int) "called 2 times" 2 !calls 673 673 674 - let test_result_unknown_error () = 674 + let result_unknown_error () = 675 675 Eio_main.run @@ fun env -> 676 676 let clock = Eio.Stdenv.clock env in 677 677 let config = ··· 694 694 695 695 (* Large retry count test *) 696 696 697 - let test_many_retries () = 697 + let many_retries () = 698 698 Eio_main.run @@ fun env -> 699 699 let clock = Eio.Stdenv.clock env in 700 700 let config = ··· 717 717 [ 718 718 ( "config", 719 719 [ 720 - Alcotest.test_case "default config" `Quick test_default_config; 721 - Alcotest.test_case "config defaults" `Quick test_config_defaults; 722 - Alcotest.test_case "config custom" `Quick test_config_custom; 723 - Alcotest.test_case "config partial" `Quick test_config_partial; 724 - Alcotest.test_case "pp_config" `Quick test_pp_config; 720 + Alcotest.test_case "default config" `Quick default_config; 721 + Alcotest.test_case "config defaults" `Quick config_defaults; 722 + Alcotest.test_case "config custom" `Quick config_custom; 723 + Alcotest.test_case "config partial" `Quick config_partial; 724 + Alcotest.test_case "pp_config" `Quick pp_config; 725 725 ] ); 726 726 ( "backoff", 727 727 [ 728 - Alcotest.test_case "test vectors (no cap)" `Quick 729 - test_backoff_test_vectors; 728 + Alcotest.test_case "test vectors (no cap)" `Quick backoff_test_vectors; 730 729 Alcotest.test_case "test vectors (default config)" `Quick 731 - test_backoff_default_config_vectors; 732 - Alcotest.test_case "AWS-style backoff" `Quick test_backoff_aws_style; 733 - Alcotest.test_case "GCP-style backoff" `Quick test_backoff_gcp_style; 734 - Alcotest.test_case "no jitter" `Quick test_backoff_no_jitter; 735 - Alcotest.test_case "exponential" `Quick test_backoff_exponential; 736 - Alcotest.test_case "capped" `Quick test_backoff_capped; 737 - Alcotest.test_case "with jitter" `Quick test_backoff_with_jitter; 738 - Alcotest.test_case "zero factor" `Quick test_backoff_zero_factor; 739 - Alcotest.test_case "attempt zero" `Quick test_backoff_attempt_zero; 730 + backoff_default_config_vectors; 731 + Alcotest.test_case "AWS-style backoff" `Quick backoff_aws_style; 732 + Alcotest.test_case "GCP-style backoff" `Quick backoff_gcp_style; 733 + Alcotest.test_case "no jitter" `Quick backoff_no_jitter; 734 + Alcotest.test_case "exponential" `Quick backoff_exponential; 735 + Alcotest.test_case "capped" `Quick backoff_capped; 736 + Alcotest.test_case "with jitter" `Quick backoff_with_jitter; 737 + Alcotest.test_case "zero factor" `Quick backoff_zero_factor; 738 + Alcotest.test_case "attempt zero" `Quick backoff_attempt_zero; 740 739 ] ); 741 740 ( "with_retry", 742 741 [ 743 - Alcotest.test_case "success first try" `Quick test_success_first_try; 744 - Alcotest.test_case "retry then success" `Quick test_retry_then_success; 745 - Alcotest.test_case "exhaust retries" `Quick test_exhaust_retries; 746 - Alcotest.test_case "should_retry false" `Quick test_should_retry_false; 747 - Alcotest.test_case "selective retry" `Quick test_selective_retry; 742 + Alcotest.test_case "success first try" `Quick success_first_try; 743 + Alcotest.test_case "retry then success" `Quick retry_then_success; 744 + Alcotest.test_case "exhaust retries" `Quick exhaust_retries; 745 + Alcotest.test_case "should_retry false" `Quick should_retry_false; 746 + Alcotest.test_case "selective retry" `Quick selective_retry; 748 747 Alcotest.test_case "selective retry permanent" `Quick 749 - test_selective_retry_permanent_failure; 750 - Alcotest.test_case "zero retries" `Quick test_zero_retries; 748 + selective_retry_permanent_failure; 749 + Alcotest.test_case "zero retries" `Quick zero_retries; 751 750 Alcotest.test_case "success on last attempt" `Quick 752 - test_success_on_last_attempt; 751 + success_on_last_attempt; 753 752 Alcotest.test_case "different exception types" `Quick 754 - test_different_exception_types; 753 + different_exception_types; 755 754 Alcotest.test_case "non-retryable exception" `Quick 756 - test_non_retryable_exception; 757 - Alcotest.test_case "many retries" `Quick test_many_retries; 755 + non_retryable_exception; 756 + Alcotest.test_case "many retries" `Quick many_retries; 758 757 ] ); 759 758 ( "with_retry_result", 760 759 [ 761 - Alcotest.test_case "success first try" `Quick 762 - test_result_success_first_try; 763 - Alcotest.test_case "retry" `Quick test_result_retry; 764 - Alcotest.test_case "exhaust retries" `Quick 765 - test_result_exhaust_retries; 760 + Alcotest.test_case "success first try" `Quick result_success_first_try; 761 + Alcotest.test_case "retry" `Quick result_retry; 762 + Alcotest.test_case "exhaust retries" `Quick result_exhaust_retries; 766 763 Alcotest.test_case "should_retry false" `Quick 767 - test_result_should_retry_false; 768 - Alcotest.test_case "selective retry" `Quick 769 - test_result_selective_retry; 770 - Alcotest.test_case "permanent error" `Quick 771 - test_result_permanent_error; 772 - Alcotest.test_case "zero retries" `Quick test_result_zero_retries; 764 + result_should_retry_false; 765 + Alcotest.test_case "selective retry" `Quick result_selective_retry; 766 + Alcotest.test_case "permanent error" `Quick result_permanent_error; 767 + Alcotest.test_case "zero retries" `Quick result_zero_retries; 773 768 Alcotest.test_case "success on last attempt" `Quick 774 - test_result_success_on_last_attempt; 775 - Alcotest.test_case "typed errors" `Quick test_result_typed_errors; 769 + result_success_on_last_attempt; 770 + Alcotest.test_case "typed errors" `Quick result_typed_errors; 776 771 Alcotest.test_case "typed permanent error" `Quick 777 - test_result_typed_permanent_error; 778 - Alcotest.test_case "unknown error" `Quick test_result_unknown_error; 772 + result_typed_permanent_error; 773 + Alcotest.test_case "unknown error" `Quick result_unknown_error; 779 774 ] ); 780 775 ]