Skip to content

Data track integration#1820

Draft
1egoman wants to merge 83 commits intomainfrom
data-track-integration
Draft

Data track integration#1820
1egoman wants to merge 83 commits intomainfrom
data-track-integration

Conversation

@1egoman
Copy link
Contributor

@1egoman 1egoman commented Feb 20, 2026

Integrates the data track managers (both incoming and outgoing) into the existing sdk Room and RemoteParticipant interfaces. Once this is merged, data tracks is fully implemented!

NOTE: This pull request is based on top of the data-track-incoming-manager branch and the diff will be weird until that one is merged here.

Interface - Publishing

const localDataTrack = await room.publishDataTrack({name: "data track name"});
await localDataTrack.tryPush(new Uint8Array(/* ... */));

// Once you are done with the local data track, it can be unpublished:
await localDataTrack.unpublish();

Interface - Subscribing

// There are two ways to get a remote data track, either a room event:
room.on(RoomEvent.RemoteDataTrackPublished, async (remoteDataTrack) => {
  // ...
});

// Or a new field on `RemoteParticipant`:
const remoteDataTrack = remoteParticipant.dataTracks.get("track name"); // Get a data track which has been published
const remoteDataTrack = await remoteParticipant.dataTracks.waitUntilExists("track name"); // Get a data track which _will_ be published shortly

// Either way, once you have a remoteDataTrack, you can subscribe:
const stream = await remoteDataTrack.subscribe(/* optional abort signal */);
for await (const frame of stream) {
  console.log(`Received bytes from ${remoteDataTrack.info.name}:`, frame.payload);
}

Todo:

…in Throws wherever possible

This is a LOT cleaner!
1egoman added 22 commits March 5, 2026 15:01
this.localParticipant = new LocalParticipant(...) takes the outgoing
data track manager, which needs the e2ee manager, and the e2ee manager
can only be constructed if this.localParticipant is set.
Been writing a little too much rust lately...
@1egoman 1egoman force-pushed the data-track-integration branch from 6a5960d to 2e6f8cf Compare March 5, 2026 20:51
@1egoman 1egoman changed the title (WIP) Data track integration Data track integration Mar 5, 2026
@ladvoc ladvoc self-requested a review March 6, 2026 22:09
*/
waitUntilExists(key: K): Promise<V>;
waitUntilExists(key: K, signal: AbortSignal): Promise<Throws<V, WaitableMapAbortError>>;
async waitUntilExists(key: K, signal?: AbortSignal) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: naming

alternative suggestions:

  • await(key)
  • getAsync(key)

My take is that await(key) might be the cleanest. The getAsync isn't really a common pattern in JS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will admit, I am not a big fan of either of those naming suggestions. To me await on its own doesn't make it clear that there is "getting a key" involved, and I also am not a super big fan of the repetition of await map.await("key").

Just to throw a few more options out there to see if we can find one we both like, here's some more potential options from a LLM:

  • resolve(key) — Borrows from Promise terminology; implies the value will materialize.
  • getDeferred(key) — Concise, borrows from the well-understood deferred/promise pattern.
  • getEventually(key) — A little whimsical but honest about what's happening.
  • getWhenAvailable(key) — Very explicit and self-documenting, though a bit long.
  • getWhen(key) — Reads as "get when available," compact shortening of the above.
  • getOnce(key) — Reads as "get once it's ready."

Thoughts on any of those?

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.

2 participants