Repository navigation
FP 3.0.0 / RC 2.0.0: route steps and templates on transformer stacks, plus performance - #34
Merged
Merged
Conversation
…es are transformer stacks
Route steps are Kleisli arrows into ReaderTPublisher (RouteEffect<Env, O>), so
>=> is the stack's lawful bind instead of an operator on the nested
Reader<Env, Publisher> shape, which RC 2 removed. Router keeps handle(_:)
returning the plain Reader; the stack is its `pipeline`.
render and loadTemplate return ReaderTResult, so `loadTemplate(name) >>- { render($0, ctx) }`
keeps its meaning under FP 3 (on a bare Reader, >>- is Reader's bind).
HTMLEnvironment is Sendable.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NRQYrVoN7VHHinrt7TxhV3
Templates render into one output buffer (each item of #each was appended
by copying everything rendered so far), read each fragment once per
render, and find {{ }} on UTF-8 bytes. esc/escAttr make one pass and
return the input untouched when there is nothing to escape.
Router is a list of routes: <|> concatenates (associative, empty is the
identity) and one publisher tries them in order, instead of one nested
catch per route. Only a 404 falls through, as before.
Route patterns are split once, Request.path is stored, and request bodies
are no longer copied per chunk.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NRQYrVoN7VHHinrt7TxhV3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Moves NetworkTools to FP 3.0.0 and ReactiveConcurrency 2.0.0 on lawful transformer stacks, and speeds up templating and routing.
Why
RC 2 removed the operators on nested shapes, so the routing DSL's
>=>onReader<Env, Publisher>stopped compiling, and under FP 3>>-on a bareReader<Env, Result>is Reader's own bind, which breaksloadTemplate(…) >>- { render($0, ctx) }(used by PhotoCulling and CV).Changes
Port (breaking)
RouteEffect<Env, O>= RC'sReaderTPublisher<Env, ResponseError, O>;>=>is the stack's lawful Kleisli composition (first failure skips the remaining steps). DSL code is unchanged.Router.handle(_:)still returns the plainReader<Env, Publisher<Response, ResponseError>>;Router.pipelineis the stack form.render/loadTemplatereturnReaderTResult<HTMLEnvironment, TemplateError, String>; the>>-chain keeps its meaning. Callers add.rawValuebeforerunReader.HTMLEnvironmentisSendable(the stack bind needs it).>>-/<*>/£>, stream<*>, Publisher>>-).Performance
#eachcopied everything rendered so far for every item), read each fragment once per render (an#includeinside#eachwas read once per item), and find{{ }}on UTF-8.esc/escAttr: one pass, input returned untouched when nothing needs escaping.Routeris a list of routes:<|>concatenates (associative,emptyis the identity, new law tests) and one publisher tries the routes in order instead of one nestedcatchper route. Only a 404 falls through, as before.Request.pathis stored, request bodies are not copied per chunk.#each1k rows with#include#each1k cellsesc, 11 KB proseesc, 9 KB nothing to escapeescAttr, 11 KB proseRouting still costs ~35 µs per route tried: one RC publisher run each. That goes away with the deferred RC same-queue dispatch, not here.
Tests: 123 pass (new: stack bind and short-circuit, fragment read once, multi-byte escaping, router identity / associativity / non-404 stops fall-through).
🤖 Generated with Claude Code
https://claude.ai/code/session_01NRQYrVoN7VHHinrt7TxhV3