Skip to content
C.W.K.
Stream
Lesson 03 of 05 · published

Emit and Receive Nothing Back

~12 min · coupling, async, callbacks, cli-contract

Level 0Cold Workshop
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

The Asymmetry Is the Point

The calling side emits a pointer. Then nothing comes back. No completion callback, no status field to poll, no result written into its database, no notification. It never learns whether a video was made, how long it ran, or whether the job failed. From the caller's perspective, pressing the button is the end of the story.

That feels wrong the first time you see it. Every instinct says a request should have a response. But look at what a response would require: to receive a status, the caller needs a model of what statuses exist — which are stages, which are failure modes, which are terminal. To receive a result, it needs a model of what a result is. Both of those are video knowledge, and the previous lesson's prohibition just came back through the return path.

Where the Answer Actually Lives

This is not a system where nobody can find out what happened. The information exists — it just lives in the message thread rather than in the caller. The discussion, the verdicts, the render path, and the closing all accumulate there, and a person reads them there. Closing the request is what shipping means.

So the question "is it done?" has an answer; it is simply not the caller's question. That reframing is the whole trick. A great many status fields exist because somebody assumed the initiating system must also be the tracking system, and those two roles genuinely can be separate — especially when the tracking audience is a human who is already reading the thread for other reasons.

A Command-Line Contract, Not a Network One

One more thing keeps this honest. The word "outsourcing" invites the reader to imagine an API call, and there isn't one. The workshop has no server to call. What crosses the boundary is a message that a person picks up, and then that person runs a command-line tool. The seam is asynchronous in the strongest sense: the two halves are not connected by a protocol at all, only by a durable message and a human who reads it.

That has a real consequence for reliability. There is no timeout to tune, no retry policy, no dead-letter queue, no partial failure where the request was received but the response was lost. The request either exists in the thread or it doesn't. Systems that can be built this way are unreasonably robust, and the reason is that they removed the network rather than hardening it.

Code

Two shapes for the same handoff·text
COUPLED — the caller tracks the work

  caller ──request──▶ worker
     ▲                   │
     └────status─────────┘

  the caller now needs:
    a status vocabulary   (which states exist?)
    a result model        (what came back?)
    a failure model       (what does retry mean?)
    a timeout policy      (how long is too long?)
  ...all of which are the worker's domain knowledge, leaking backward.


ONE-WAY — the thread tracks the work

  caller ──pointer──▶ [ durable thread ] ◀──reads/writes── person
                                              │
                                              ▼
                                          workshop (CLI)

  the caller needs: nothing. it emitted and it is done.
The version that looks helpful and is the trap·python
# TEMPTING - and it re-imports the whole domain through the back door.
class RenderStatus(str, Enum):
    QUEUED = "queued"
    FETCHING = "fetching"      # <- a stage name. that is video knowledge.
    SYNTHESIZING = "synthesizing"
    ENCODING = "encoding"
    FAILED_TTS = "failed_tts"  # <- a failure taxonomy. also video knowledge.
    DONE = "done"

# Every rename in the workshop is now a migration on the caller.
# The enum IS the coupling; the network call was never the problem.


# CHOSEN - the caller's entire model of the work:
#   (nothing)
# The thread holds the narrative; a person holds the judgment.

External links

Exercise

Find a request-reply integration you own where the reply is only ever read by a person. Write down what the calling system currently has to model in order to interpret that reply — status names, error codes, partial states. Then design the one-way version: what durable record would hold the narrative instead, and who reads it. Decide honestly whether the reply was ever load-bearing or just the default shape of a function call.
Hint
The giveaway is a status enum in the caller whose values are named after the worker's internal steps. Those names are the worker's implementation, and every rename on that side becomes a coordinated deployment on both — which is the definition of coupling you did not intend to buy.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.