
Resilience.pudu
Pudu58 lines2.5 KB
1/** @Examples.Resilience.Program — the standard resilience pipeline against a flaky server */2module Resilience34import Std.Concurrent as Concurrent5import Std.Http as Http6import Std.Http.Server.Reply as Reply7import Std.Http.Server.Route as Route8import Std.Http.Server as Server9import Std.Io as Io10import Std.Result as Result11import Std.Sync as Sync12import PuduLangHttpClient.Client as Client13import PuduLangHttpClient.Factory.Builder as Builder14import PuduLangHttpClient.Factory as Factory15import PuduLangHttpClient.Handlers.Resilience as Resilience16import PuduLangHttpClient as HttpClient17import PuduLangResilience.Retry as Retry181920fn serve(seen: &Sync.Counter) -> (Server.Running, Str) {21 let counter = *seen22 let running = match Server.start("127.0.0.1", 0) {23 case Ok(found) => found24 case Err(problem) => panic(show(problem))25 }26 let server = Server.server(&Route.routing(&[Route.get("/stock", fn(_request: Route.Request) -> Http.Response {27 let attempt = Result.unwrapOr(Sync.increment(&counter, 1), 0)28 if attempt <= 2 { Http.Response{..Reply.text(503, "busy"), headers: [("retry-after", "0")]} } else { Reply.text(200, "12 in stock") }29 })]))30 let _serving = Concurrent.start(fn() -> () { let _ran = Server.run(&server, &running, 0) })31 (running, "http://127.0.0.1:" + show(Server.portOf(&running)) + "/")32}333435fn main() -> Int {36 let seen = Sync.counter(0)37 let (running, base) = serve(&seen)38 let options = Resilience.standardOptions()39 let quick = Resilience.Standard{..options, retry: Retry.Options{..options.retry, delay: 10}}40 let pipeline = match Resilience.standardWith(&quick) {41 case Ok(built) => built42 case Err(_) => panic("the standard pipeline did not build")43 }44 let factory = match Factory.build([Builder.named("inventory").withBaseAddress(base).withHandler(Resilience.handler(pipeline))]) {45 case Ok(built) => built46 case Err(invalid) => panic(Factory.explain(&invalid))47 }48 let stock = Client.getText(&Factory.createClient(&factory, "inventory"), "stock")49 let attempts = Result.unwrapOr(Sync.count(&seen), 0)50 let _said = Io.writeLine(match stock {51 case Ok(text) => text + " after " + show(attempts) + " attempts"52 case Err(failure) => HttpClient.describe(&failure)53 })54 Factory.dispose(&factory)55 let _stopped = Server.stop(&running)56 if stock == Ok("12 in stock") && attempts == 3 { 0 } else { 1 }57}58