Skip to content

upstream reaches the UI only through wippy.session.process:plugin — any other parent is a dead end #33

Description

@xepozz

Not a patch, because the obvious fix double-delivers. Filing the analysis instead.

What happens

src/process/upstream.lua delivers to exactly one recipient:

function session_upstream:_send_message(topic, message)
    -- Send to parent process (which can relay to all connections)
    if self.parent_pid then
        process.send(self.parent_pid :: string, topic, message)
    end
end

and the only thing in the module that relays onward is src/process/plugin.lua:559-562:

elseif string.sub(topic, 1, string.len(consts.TOPIC_PREFIXES.SESSION)) == consts.TOPIC_PREFIXES.SESSION then
    if state.user_hub_pid then
        process.send(state.user_hub_pid :: string, topic, payload:data())
    end

So received, response_started, content, update and command_response reach a browser only when the parent happens to be the relay plugin. Spawn a session from anything else — a channel bridge, a job, an automation that wants the conversation visible in the UI — and every upstream update stops at that parent. The session runs correctly, the rows are written, and nothing on screen moves.

That is a supported-looking arrangement with an unsupported half: spawn a session process is a public shape, and only one of its callers gets updates.

Why conn_pid is not the answer

conn_pid looks like the missing route. It is accepted by upstream.new, stored on the instance, and refreshed by the session process on every inbound message (src/process/session.lua:209 and :237). src/process/plugin.lua threads it through spawn payloads and command payloads, and errors go straight to it via send_error. src/process/message_handlers.lua:361-363 reaches in for it as the streaming reply_to.

The one place that never reads it is the module that owns it. upstream.lua stores conn_pid and no method uses it.

I started a patch to send there as well and abandoned it: in the plugin path the parent forwards to the user hub, and the hub fans out to that user’s connections — including the one at conn_pid. Adding a direct send would deliver every update twice to the client that is actually connected. Only the maintainers can say which of these is meant to be the route.

What would settle it

One of:

  • conn_pid is vestigial — then upstream.new should stop taking it, session.lua should stop refreshing it, and message_handlers should get the connection some other way. Right now three files maintain a field with one indirect reader.
  • Forwarding is a parent’s contract — then say so where a parent is spawned, because plugin.lua is currently the only worked example and it is 649 lines.
  • The hub is the real destination — then upstream could take it directly and the plugin’s forward becomes redundant.

How I got here

Tracing why a Telegram conversation never appeared live in a Kickside UI. The cause turned out to be elsewhere (kickside/sessions 0.1.22 has no subscription at all — no WebSocket, no polling, and onHostVisibilityChanged left as the empty base method), and this deployment mirrors turns into wippy.session rows and pushes the same topics to the user hub by hand, which works.

But it means the natural fix — run the turns inside a real session process — would not have helped, and it took reading plugin.lua to find out why. That seemed worth writing down.

Related: #32.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions