Skip to content

Data tracks: publishing - #991

Merged
ladvoc merged 23 commits into
ladvoc/data-track-corefrom
ladvoc/data-track-publishing
Oct 21, 2026
Merged

ladvoc merged 23 commits into
ladvoc/data-track-corefrom
ladvoc/data-track-publishing

Conversation

@ladvoc

@ladvoc ladvoc commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

Add support for publishing data tracks.

Architecture and public API closely match Rust and JS clients:

  • The user publishes data tracks using the LocalParticipant.PublishDataTrack API.
  • A LocalManager manages internal state and transitions for all local data tracks.

Closes BOT-541

@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch from 5db4c9f to 8a5d82c Compare September 3, 2026 22:23
@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch 2 times, most recently from 6bf5d50 to ba27476 Compare September 4, 2026 22:57
@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch from ba27476 to 45535a7 Compare September 8, 2026 21:55
@ladvoc
ladvoc requested a review from boks1971 September 8, 2026 21:59
@ladvoc
ladvoc marked this pull request as ready for review September 8, 2026 22:15
@ladvoc
ladvoc requested a review from a team as a code owner September 8, 2026 22:15
devin-ai-integration[bot]

This comment was marked as resolved.

Comment thread localdatatrack.go
@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch from 45535a7 to 75474d6 Compare September 14, 2026 21:40
devin-ai-integration[bot]

This comment was marked as resolved.

@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch from 492304c to 1c91a15 Compare September 22, 2026 16:46
@ladvoc ladvoc changed the title Data track publishing Data tracks: publishing Sep 22, 2026

@boks1971 boks1971 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I have not reviewed local.go and local_test.go yet. But, I am stopping here for some comments and pick it up later after your response.

Some notes

  1. I think localDataTracks should be moved LocalParticipant fully if possible. It should just follow the media track pattern. At room level, I don't think it should be dealing with tracks. It should be dealing with only participants and tracks should live at participant. We should look at it more closely if that is not possible for some reason (I am going to leave the same comment in the subscribe PR where remote tracks if possible should be managed inside the RemoteParticipant)
  2. Because I have not fully ready the above files, I am not sure of the LocalManager (and similarly RemoteManager's roles). But for abstraction and making things private, you can do something like
type LocalManager interface {
     // only publicly needed methods here
}

type localManager struct {
     // the implementation which is package private
}

var _ LocalManager = (*localManager)(nil) // compiler trick to ensure that localManager implements the LocalManager interface.

func NewLocalManager() LocalManager{
}

Comment thread room.go Outdated
Comment thread examples/datatrack/publisher/main.go Outdated
Comment thread localdatatrack.go Outdated
Comment thread localdatatrack_test.go Outdated
@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch from 481afac to f656c06 Compare October 5, 2026 22:15
@ladvoc ladvoc mentioned this pull request Oct 5, 2026
@ladvoc

ladvoc commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

I have not reviewed local.go and local_test.go yet. But, I am stopping here for some comments and pick it up later after your response.

Some notes

  1. I think localDataTracks should be moved LocalParticipant fully if possible. It should just follow the media track pattern. At room level, I don't think it should be dealing with tracks. It should be dealing with only participants and tracks should live at participant. We should look at it more closely if that is not possible for some reason (I am going to leave the same comment in the subscribe PR where remote tracks if possible should be managed inside the RemoteParticipant)
  2. Because I have not fully ready the above files, I am not sure of the LocalManager (and similarly RemoteManager's roles). But for abstraction and making things private, you can do something like
type LocalManager interface {
     // only publicly needed methods here
}

type localManager struct {
     // the implementation which is package private
}

var _ LocalManager = (*localManager)(nil) // compiler trick to ensure that localManager implements the LocalManager interface.

func NewLocalManager() LocalManager{
}

Some additional context: the data tracks implementations follow a pattern that is gradually being adopted by the other client SDKs as part of the effort to break up the monolithic room and participant objects. The main idea is each independent feature in a room (publishing data tracks, subscribing to data tracks, RPC, etc.) keeps all of its state and business logic in one manager, separate from the the objects that comprise the public API (room, local participant, remote participant, etc.).

One benefit is that each manager can be unit tested in isolation without constructing a room or connecting to an SFU. This also allows test cases to be standardized across implementations and audited to ensure they are equivalent. For reference, here are the local manager test suites for the other implementations:

The role of each manager:

  • datatrack.LocalManager manages all data tracks published by the local participant.
  • datatrack.RemoteManager manages all data track subscriptions in the room, not just the tracks of one remote participant.

We could move LocalManager into LocalParticipant. RemoteManager is different though since its state covers the whole room, so there is no single RemoteParticipant it could belong to.

Curious to hear your thoughts given this additional context.

@boks1971

Copy link
Copy Markdown
Contributor

I have not reviewed local.go and local_test.go yet. But, I am stopping here for some comments and pick it up later after your response.
Some notes

  1. I think localDataTracks should be moved LocalParticipant fully if possible. It should just follow the media track pattern. At room level, I don't think it should be dealing with tracks. It should be dealing with only participants and tracks should live at participant. We should look at it more closely if that is not possible for some reason (I am going to leave the same comment in the subscribe PR where remote tracks if possible should be managed inside the RemoteParticipant)
  2. Because I have not fully ready the above files, I am not sure of the LocalManager (and similarly RemoteManager's roles). But for abstraction and making things private, you can do something like
type LocalManager interface {
     // only publicly needed methods here
}

type localManager struct {
     // the implementation which is package private
}

var _ LocalManager = (*localManager)(nil) // compiler trick to ensure that localManager implements the LocalManager interface.

func NewLocalManager() LocalManager{
}

Some additional context: the data tracks implementations follow a pattern that is gradually being adopted by the other client SDKs as part of the effort to break up the monolithic room and participant objects. The main idea is each independent feature in a room (publishing data tracks, subscribing to data tracks, RPC, etc.) keeps all of its state and business logic in one manager, separate from the the objects that comprise the public API (room, local participant, remote participant, etc.).

One benefit is that each manager can be unit tested in isolation without constructing a room or connecting to an SFU. This also allows test cases to be standardized across implementations and audited to ensure they are equivalent. For reference, here are the local manager test suites for the other implementations:

The role of each manager:

  • datatrack.LocalManager manages all data tracks published by the local participant.
  • datatrack.RemoteManager manages all data track subscriptions in the room, not just the tracks of one remote participant.

We could move LocalManager into LocalParticipant. RemoteManager is different though since its state covers the whole room, so there is no single RemoteParticipant it could belong to.

Curious to hear your thoughts given this additional context.

Sorry about the delay on this. That sounds good to me @ladvoc . I will read through those two managers and drop any feedback.

I am thinking LocalManager in LocalParticipant is still a good one to do rather than at room level.

Ideally, I would do a RemoteParticipantManager for all remote participants and tuck the RemoteManager in that so that there is more separation from Room there.

Comment thread datatrack/local_test.go Outdated
Comment thread datatrack/local_test.go Outdated
Comment thread internal/datatrack/local.go
Comment thread internal/datatrack/local.go
Comment thread datatrack/local.go Outdated
Comment thread internal/datatrack/local.go
Comment thread datatrack/local.go Outdated
Comment thread datatrack/local.go Outdated
@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch from f656c06 to a5467d5 Compare October 19, 2026 19:13

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 4 new potential issues.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

Comment thread localdatatrack.go
Comment thread internal/datatrack/local.go
Comment thread engine.go
Comment thread localparticipant.go
@ladvoc
ladvoc force-pushed the ladvoc/data-track-publishing branch from a5467d5 to 953bf0c Compare October 19, 2026 20:05
@ladvoc
ladvoc merged commit 96b105c into main Oct 21, 2026
9 checks passed
@ladvoc
ladvoc deleted the ladvoc/data-track-publishing branch October 21, 2026 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants