Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-httpclient

Named HTTP clients for Pudu: a client factory, delegating handlers, pooled keep-alive connections, handler lifetimes, logging, and resilience

0.1.1Apache-2.01

InstallClose

Entry.pudu

Pudu65 lines2.5 KB

GitHub ↗
1/** @Factory.Entry.Module — one built handler pipeline, its transport, and when it was built */2module PuduLangHttpClient.Factory.Entry34import PuduLangHttpClient.Factory.Builder as Builder5import PuduLangHttpClient.Handler as Handler6import PuduLangHttpClient.Transport as Transport78/** @Factory.Entry.Entry — a pipeline built for a name, reused until its lifetime runs out */9export type Entry = {10  name: Str,11  generation: Int,12  send: Handler.Send,13  transport: Option[Transport.Transport],14  created: Int,15  lifetime: Int,16  expiredAt: Option[Int]17}1819/// The pipeline the builder describes, built now: observers outermost, then the handlers in the20/// order added and as rearranged, then the observers' inner handlers, around a new primary handler.21export fn build(builder: &Builder.Builder, generation: Int) -> Entry {22  let (transport, primary) = match builder.primary {23    case Some(Builder.Custom(make)) => (None, make())24    case Some(Builder.Pooled(options)) => pooled(transportOptions(builder, options))25    case None => pooled(transportOptions(builder, Transport.defaults()))26  }27  Entry {28    name: builder.name,29    generation: generation,30    send: Handler.compose(&layers(builder), primary),31    transport: transport,32    created: clock(),33    lifetime: Builder.lifetimeOf(builder),34    expiredAt: None35  }36}3738/// Every handler of the pipeline, outermost first.39export fn layers(builder: &Builder.Builder) -> Array[Handler.Handler] {40  let observation = Builder.Observation{name: builder.name, redact: Builder.redaction(builder)}41  var added = builder.handlers.map(|make: fn() -> Handler.Handler| make())42  for edit in builder.handlerEdits { added = edit(added) }43  let outer = builder.observers.map(|observer: Builder.Observer| (observer.outer)(observation))44  let inner = builder.observers.reverse().map(|observer: Builder.Observer| (observer.inner)(observation))45  outer.concat(added).concat(inner)46}4748/// Closes the entry's transport, when it has one.49export fn close(entry: &Entry) -> () {50  if let Some(transport) = entry.transport { Transport.close(&transport) }51}5253/// A new transport and its sender.54fn pooled(options: Transport.Options) -> (Option[Transport.Transport], Handler.Send) {55  let made = Transport.create(options)56  (Some(made), Transport.send(&made))57}5859/// The transport options with the builder's edits applied in order.60export fn transportOptions(builder: &Builder.Builder, options: Transport.Options) -> Transport.Options {61  var edited = options62  for edit in builder.transportEdits { edited = edit(edited) }63  edited64}65