Laughter.Rewriter.Session (Laughter v0.3.0)

Copy Markdown

Temporary OTP session for one dynamic element selector plus native rules.

Supervise with {Laughter.Rewriter.Session, {plan, owner: owner, selector: "a"}}. The explicit owner is monitored; a session is not restarted because consumed input cannot be replayed. Laughter.Rewriter.start_link/2 defaults the owner to the caller. All commands must come from that owner.

Grant one output credit with demand/1, then write/2 or finish/1. A write acknowledges acceptance immediately and does not wait for element replies. Only one chunk may be in flight. Output (including an empty binary) acknowledges its completion. Grant another credit before the next write or final flush.

Messages sent to the owner:

  • {:laughter, session, request_ref, {:element, tag, attrs}}
  • {:laughter, session, {:output, chunk_ref, binary}}
  • {:laughter, session, :done} — after the final output
  • {:laughter, session, {:error, reason}} — terminal failure/cancellation

Reply with reply/3 and a list of mutation tuples, e.g. [{:set_attribute, "href", "/new"}, {:append_text, "!"}], or [] to keep it. Native rules run first; removed/replaced elements do not generate requests. The snapshot includes native attribute changes. Inserted HTML is not reparsed.

Options: required :owner and :selector; :chunk_size (65,536 bytes), :max_output_bytes (1,048,576 bytes), :reply_timeout (5,000 milliseconds), and :max_reply_bytes (1,048,576 external-term bytes, at most 128 mutations). The plan supplies the encoding and parser memory limit. Oversized writes are rejected rather than split. Previously emitted output cannot be rolled back.

This opt-in mode uses one native worker thread per session. No BEAM scheduler waits for replies and there is no polling. Use native stream/3 when decisions do not need Elixir. Limits bound native buffers and in-flight work, not data retained in the owner's mailbox; only request output you can consume.

Summary

Functions

Cancels the session, discarding pending output.

Returns a specification to start this module under a supervisor.

Grants one output credit. Does not accumulate credits.

Accepts EOF; requires output demand for the final flush.

Replies to the current element request. Invalid replies may be corrected before timeout.

Accepts one bounded chunk, returning its output reference without waiting for parsing.

Functions

cancel(session)

@spec cancel(pid()) :: :ok | {:error, term()}

Cancels the session, discarding pending output.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

demand(session)

@spec demand(pid()) :: :ok | {:error, term()}

Grants one output credit. Does not accumulate credits.

finish(session)

@spec finish(pid()) :: {:ok, reference()} | {:error, term()}

Accepts EOF; requires output demand for the final flush.

reply(session, ref, mutations)

@spec reply(pid(), reference(), [Laughter.Rewriter.reply_mutation()]) ::
  :ok | {:error, term()}

Replies to the current element request. Invalid replies may be corrected before timeout.

start_link(arg)

@spec start_link({Laughter.Rewriter.t(), keyword()}) :: GenServer.on_start()

write(session, chunk)

@spec write(pid(), iodata()) :: {:ok, reference()} | {:error, term()}

Accepts one bounded chunk, returning its output reference without waiting for parsing.