Skip to content

Subscriber: final response in "terminated", unsubscribe on UA.stop() - #978

Open
neutrino38 wants to merge 1 commit into
versatica:masterfrom
neutrino38:subscriber-response-and-stop
Open

neutrino38 wants to merge 1 commit into
versatica:masterfrom
neutrino38:subscriber-response-and-stop

Conversation

@neutrino38

Copy link
Copy Markdown

What

  • terminated gets the final response as a 4th argument: (code, reason, retryAfter, response). It is set for SUBSCRIBE_NON_OK_RESPONSE,
    SUBSCRIBE_AUTHENTICATION_FAILED, SUBSCRIBE_WRONG_OK_RESPONSE and the new UNSUBSCRIBED_ON_UA_STOP, and undefined otherwise. Existing listeners are not affected.
  • The constructor validates the target and throws TypeError: Invalid target: …, as Message and Options do. The normalized URI is kept and reused for the initial
    SUBSCRIBE.
  • After terminate():
    • the pending refresh is cancelled;
    • the 2xx to the un-SUBSCRIBE no longer schedules a refresh;
    • if no final NOTIFY arrives within C.FINAL_NOTIFY_TIMEOUT_SEC (32 s, like Timer F), the subscription ends with UNSUBSCRIBE_TIMEOUT. That code was declared but never
      emitted.
  • UA.stop() unsubscribes every subscription that has been sent. The UA tracks subscribers through newSubscriber() and destroySubscriber(), as it does for sessions,
    and calls terminate() on each one before closing. A stopped UA drops in Jump to bottom (ctrl+End) ↓ e final NOTIFY, so a subscriber in that situation ends on the 2xx to its

Behaviour changes

  • ua.subscribe() with an invalid target now throws from the constructor. Before, it sent a malformed request.
  • A new termination code: UNSUBSCRIBED_ON_UA_STOP = 8.
  • Apps that called terminate() on every subscriber before ua.stop() keep working: terminate() is idempotent.

Known limitation

If ua.stop() is called while an initial SUBSCRIBE is still waiting for its response, the un-SUBSCRIBE is queued (no dialog exists yet). It is only sent once the 2xx arrives,
and by then the UA is closed. This is the same as before for terminate() in that state. Fixing it would mean changing RequestSender's behaviour on a closed UA, which is out
of scope here.

- The `terminated` event gets the final response as a 4th argument.
  SUBSCRIBE_NON_OK_RESPONSE covers 404 and 489 alike, which call for
  different reactions (retry later vs. the server has no such event
  package).
- An invalid target throws TypeError in the constructor, as
  UA.sendMessage() does, instead of sending `SUBSCRIBE undefined`.
- terminate() cancels the pending refresh, and the 2xx to the
  un-SUBSCRIBE no longer schedules a new one (it used to re-SUBSCRIBE
  after Expires: 0 when the final NOTIFY was lost). If no final NOTIFY
  comes within 32 s, the subscription ends with UNSUBSCRIBE_TIMEOUT,
  a code that was declared but never emitted.
- UA.stop() unsubscribes every subscription it knows of, as it
  terminates sessions, so that the server does not keep notifying a
  gone UA until the subscription expires. A stopped UA drops incoming
  requests, the final NOTIFY included: such a subscription ends on the
  2xx to its un-SUBSCRIBE, with the new code UNSUBSCRIBED_ON_UA_STOP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant