Skip to content

Ergonomic announced streams in Swift and Kotlin wrappers#1554

Merged
kixelated merged 2 commits into
devfrom
claude/affectionate-borg-362ea9
May 30, 2026
Merged

Ergonomic announced streams in Swift and Kotlin wrappers#1554
kixelated merged 2 commits into
devfrom
claude/affectionate-borg-362ea9

Conversation

@kixelated

@kixelated kixelated commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

The announced subscription was awkward to consume in the language wrappers: you acquired a handle and then called a separate stream member whose name stuttered against the handle (announced.announcements() / announced.announcements). This reworks the Swift and Kotlin wrappers so each stream reads idiomatically in its own language. moq-ffi is untouched on purpose. uniffi can't carry a stream across the FFI boundary, so the pull-based next() handle is the only option and the ergonomics belong in the wrappers (Python already does this).

  • Swift: MoqAnnounced now conforms to AsyncSequence, so the handle iterates directly:
    for try await announcement in announced { ... }
  • Kotlin: replaced the stuttering MoqAnnounced.announcements() extension with a fused MoqOriginConsumer.announcements(prefix): Flow that acquires the subscription on first collection and cancels it via try/finally (forwarding cancellation on every completion path, not just CancellationException):
    consumer.announcements("demos/").collect { announcement -> ... }
    This matches how the other consumers already pair a low-level next() with a Flow extension.

Docs and per-language READMEs are updated to the new call sites.

Go deferred

Go was dropped from this PR. Its bindings have no ergonomic layer at all (every stream is raw), and bringing it to parity is entangled with a larger open question: whether the compiled-FFI wrappers (Swift/Kotlin/Go) should move to a Python-style hand-written wrapper layer, and whether to drop the moq.MoqClient stutter. That's a deliberate, separately-scoped refactor rather than a rider on this announced-ergonomics change.

Why dev

This is a breaking change to the public Swift/Kotlin wrapper APIs (the old .announcements member is gone), which per the branch-targeting rule belongs on dev. It also builds naturally on the auto-origin session rework already on dev (cs.consumer() etc.), which the updated docs use.

Design note for reviewers

Teardown-on-abandon differs slightly between the two, pre-existing and left as-is: Swift cancels on any stream termination; Kotlin cancels on coroutine cancellation (the new fused announcements also cancels the handle it acquired via try/finally).

Test plan

  • Swift: just swift builds + smoke tests pass, no @retroactive/conformance warnings.
  • Kotlin: signatures verified against generated bindings, but Gradle wasn't available locally for a full just kt check.

(Written by Claude)

kixelated added 2 commits May 30, 2026 07:31
The announced subscription forced an awkward two-step in the wrappers:
acquire a handle, then call a separate stream member that stuttered against
the handle name (announced.announcements). moq-ffi can't help here. uniffi
can't carry a stream across the FFI boundary, so the next()-based handle is
the only option and the ergonomics belong in each wrapper.

- Swift: MoqAnnounced now conforms to AsyncSequence, so the handle iterates
  directly (for try await a in announced).
- Kotlin: replace the MoqAnnounced.announcements() extension with a fused
  MoqOriginConsumer.announcements(prefix): Flow that acquires the
  subscription on collection and cancels it via try/finally. This matches
  how the other consumers pair a low-level next() with a Flow extension.
- Go: add range-over-func iter.Seq2 iterators for the whole stream set
  (Announcements, Groups, GroupsAsArrived, Frames, Updates); Go previously
  had no ergonomic layer at all. Bumps go.mod to 1.23 for iter.

Docs and per-language READMEs updated to the new call sites; doc/lib/go
gains a Subscribe example it was missing.
@kixelated kixelated changed the title Ergonomic announced streams in Swift, Kotlin, and Go wrappers Ergonomic announced streams in Swift and Kotlin wrappers May 30, 2026
@kixelated kixelated enabled auto-merge (squash) May 30, 2026 15:25
@kixelated kixelated merged commit 19df38e into dev May 30, 2026
2 checks passed
@kixelated kixelated deleted the claude/affectionate-borg-362ea9 branch May 30, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant