Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
b9e4b76
chore(quest): claim quest/m1/ietf-epoch-cut.md
kixelated Oct 29, 2026
ef868a0
feat(net)!: remove epochs from moq-transport
kixelated Oct 29, 2026
46cbf0e
chore(quest): record epoch-cut validation still awaiting host admission
kixelated Oct 29, 2026
6f0e4c1
Merge origin/main into quest/m1/ietf-epoch-cut
kixelated Oct 31, 2026
3b3a10d
fix(net): drop the EPOCH fields main's new tests still set
kixelated Oct 31, 2026
cb17515
test(net): drop moq-transport resumption cases main added
kixelated Oct 31, 2026
60c8cd3
chore(quest): finish quest/m1/ietf-epoch-cut
kixelated Oct 31, 2026
2be80f1
Merge origin/main into quest/m1/ietf-epoch-cut
kixelated Oct 31, 2026
46249bb
test(e2ee): assert moq-transport delivers no route epoch
kixelated Oct 31, 2026
f169a94
Merge origin/main into quest/m1/ietf-epoch-cut
kixelated Oct 31, 2026
0cd79a3
Merge base and resolve epoch-removal conflicts mechanically
Nov 1, 2026
846eb14
docs: repair links to retired epoch removal quest
Nov 1, 2026
3cf8b71
Merge remote-tracking branch 'origin/main' into worktree-agent-ad1e65…
kixelated Nov 1, 2026
ce9462d
chore(quest): claim quest/m1/api-audit/route/identity.md
kixelated Nov 1, 2026
bddbbf7
Merge commit '3cf8b71065' into quest/m1/api-audit/route/identity
kixelated Nov 1, 2026
b32cb26
feat(net)!: routes carry an identity and a per-identity epoch
kixelated Oct 31, 2026
ddeb796
fix(net): a takeover continues requests pinned to its predecessor's i…
kixelated Nov 1, 2026
31364b0
feat!: catalogs, archives and tools name streams by identity
kixelated Oct 31, 2026
e100a97
feat(ffi)!: bindings name streams by identity
kixelated Oct 31, 2026
a0a95e6
feat(js)!: @moq/net routes carry an identity and a per-identity epoch
kixelated Oct 31, 2026
eadc295
docs: identity and epoch replace publisher epochs
kixelated Oct 31, 2026
eb1af31
fix(js): decide epoch supersession among the routes a reader sees
kixelated Oct 31, 2026
279a92a
fix(js): supersede a local broadcast by any visible route, per prefix
kixelated Oct 31, 2026
2f417d8
fix(js): weigh a local broadcast against the routes its caller may use
kixelated Oct 31, 2026
43211df
chore: regenerate bindings, format, and drop the unused JS uuid depen…
kixelated Nov 1, 2026
118f4ee
refactor: name identities identity, not epoch
kixelated Nov 1, 2026
1955586
chore(quest): finish quest/m1/api-audit/route/identity.md
kixelated Nov 1, 2026
2d6b30f
fix(js): keep a leading byte order mark in a wire identity
kixelated Nov 1, 2026
e192275
Merge remote-tracking branch 'origin/main' into quest/m1/api-audit/ro…
kixelated Nov 1, 2026
e17ca29
test(hang): the parity fixture refuses an empty identity, not a malfo…
kixelated Nov 1, 2026
5542a40
Merge remote-tracking branch 'origin/main' into quest/m1/api-audit/ro…
kixelated Nov 1, 2026
4883e3b
fix: name identities in the code main added since the last merge
kixelated Nov 1, 2026
bb5880f
Merge remote-tracking branch 'origin/main' into quest/m1/api-audit/ro…
kixelated Nov 1, 2026
86b388b
fix: name identities in tests main added since the last merge
kixelated Nov 1, 2026
e4c6cea
test(hls): an open stream keeps its URLs under its identity after the…
kixelated Nov 1, 2026
6bbb80b
test(c): prove a re-announced stream is delivered again without a rac…
kixelated Nov 1, 2026
cefa9d9
Merge remote-tracking branch 'origin/main' into quest/m1/api-audit/ro…
kixelated Nov 1, 2026
8bde201
Merge origin/main into quest/m1/api-audit/route/identity
kixelated Nov 1, 2026
3d64ff3
fix(net): port main's new tests onto identities
kixelated Nov 1, 2026
86fec66
refactor(net)!: rename the route identity to instance
kixelated Nov 1, 2026
a94f932
docs: explain the instance and carry the rename into MIGRATE notes an…
kixelated Nov 1, 2026
59d2105
fix(net): port main's withdrawal-while-opening test onto a minted ins…
kixelated Nov 1, 2026
e54275c
perf(net): rank route candidates against one per-instance epoch table
kixelated Nov 2, 2026
3e27d7b
Merge origin/main into quest/m1/api-audit/route/identity
kixelated Nov 2, 2026
1a04419
Merge remote-tracking branch 'origin/main' into iterate-7489
kixelated Nov 2, 2026
bd4e2cf
fix: log a received instance escaped
kixelated Nov 2, 2026
9ed5b91
docs: a named instance should not start with the minted mark
kixelated Nov 2, 2026
efeedf2
fix(net): an ended advertisement retires its minted instance
kixelated Nov 2, 2026
93fbfce
fix(js): a pinned request follows its own instance's routes
kixelated Nov 2, 2026
9569baa
style: rustfmt the instance fixes
kixelated Nov 2, 2026
63ce3c9
Merge origin/main into quest/m1/api-audit/route/identity
kixelated Nov 2, 2026
5b07a6a
chore(quest): instance encoding covers DASH URLs too
kixelated Nov 2, 2026
75486ea
Merge origin/main into quest/m1/api-audit/route/identity
kixelated Nov 2, 2026
c1953d0
chore(quest): restate the leave-restart quest for instances
kixelated Nov 2, 2026
06677bd
fix(net): a follower re-resolves only once its instance stops serving
kixelated Nov 2, 2026
84b6e30
Merge origin/main into quest/m1/api-audit/route/identity
kixelated Nov 2, 2026
88b2870
test(ffi): a dropped takeover waits for the next instance
kixelated Nov 2, 2026
8b3fc60
Merge origin/main into quest/m1/api-audit/route/identity
kixelated Nov 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion c/moq/MIGRATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Publish a replacement under a new name, and expect a finished track's demand ter
### A claim answers by publishing (#5678)

`moq_origin_dynamic` takes no route, and `moq_origin_dynamic_update` is gone.
`moq_broadcast_request_accept` is replaced by `moq_broadcast_request_prepare`, which returns a prepared answer under the epoch you pass: fill its broadcast, then `moq_broadcast_prepared_publish` announces it at the exact path under that epoch.
`moq_broadcast_request_accept` is replaced by `moq_broadcast_request_prepare`, which returns a prepared answer: fill its broadcast, then `moq_broadcast_prepared_publish` announces it at the exact path under a fresh instance of its own.
`moq_broadcast_prepared_free` refuses an answer you will not publish.

### `moq_track_info` gains `compress` (#5928)
Expand Down
2 changes: 1 addition & 1 deletion cpp/moq/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# moq C++ package

C++17 bindings for [rs/moq-ffi](../../rs/moq-ffi): the sources `uniffi-bindgen-cpp` generates, plus `include/moq/moq.hpp`, a thin layer that adds the executor, shutdown, and `co_await` glue. `uniffi.toml` strips moq-ffi's `Moq` type prefix and `moq_` function prefix, so `MoqClient` is generated as `moq::Client` and `moq_mint_epoch` as `moq::mint_epoch`. Nothing here re-implements a method; a shape problem is fixed in moq-ffi, where every binding benefits. User docs: [doc/lib/cpp](../../doc/lib/cpp/index.md).
C++17 bindings for [rs/moq-ffi](../../rs/moq-ffi): the sources `uniffi-bindgen-cpp` generates, plus `include/moq/moq.hpp`, a thin layer that adds the executor, shutdown, and `co_await` glue. `uniffi.toml` strips moq-ffi's `Moq` type prefix and `moq_` function prefix, so `MoqClient` is generated as `moq::Client` and `moq_log_level` as `moq::log_level`. Nothing here re-implements a method; a shape problem is fixed in moq-ffi, where every binding benefits. User docs: [doc/lib/cpp](../../doc/lib/cpp/index.md).

## Layout

Expand Down
5 changes: 0 additions & 5 deletions cpp/obs/src/moq-dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,11 +1124,6 @@ void MoQDock::StartStream()
return;
}

if (auto *moq = static_cast<MoQOutput *>(obs_obj_get_data(output))) {
const auto epoch = moq->GetEpoch();
if (!epoch.empty())
publishSummary += QStringLiteral("\nEpoch ") + QString::fromStdString(epoch);
}
pollTimer->start();

SetRunning(true);
Expand Down
15 changes: 3 additions & 12 deletions cpp/obs/src/moq-output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ bool MoQOutput::Start()
}

// Create the broadcast on an origin of our own, then announce it so subscribers
// can discover it. Stop() finishes it, so each Start creates a fresh one. Only the
// can discover it. Stop() finishes it, so each Start creates a fresh one, under a
// fresh instance the broadcast mints and keeps across reconnects. Only the
// broadcast is kept: the route outlives the publication until the broadcast closes.
LOG_INFO("Publishing broadcast: %s", path.c_str());
auto next_origin = moq::OriginProducer::init(moq::OriginConfig{});
Expand All @@ -176,9 +177,7 @@ bool MoQOutput::Start()
LOG_ERROR("Failed to create broadcast: %s", publication.error().to_string().c_str());
return false;
}
moq::AnnounceRoute route;
route.epoch = moq::mint_epoch();
if (auto announced = (*publication)->announce(route); !announced) {
if (auto announced = (*publication)->announce({}); !announced) {
LOG_ERROR("Failed to announce broadcast: %s", announced.error().to_string().c_str());
return false;
}
Expand Down Expand Up @@ -229,7 +228,6 @@ bool MoQOutput::Start()
{
std::lock_guard<std::mutex> lock(mutex);
url = server;
epoch = *route.epoch;
}
{
std::lock_guard<std::mutex> lock(media_mutex);
Expand Down Expand Up @@ -371,7 +369,6 @@ void MoQOutput::Reset()
connected = false;
live = false;
url.clear();
epoch.clear();
last_failure_code = MoQError::None;
last_failure_reason.clear();
token_refusal.clear();
Expand Down Expand Up @@ -428,12 +425,6 @@ void MoQOutput::Reset()
SetBitrate(encoder, bitrate);
}

std::string MoQOutput::GetEpoch()
{
std::lock_guard<std::mutex> lock(mutex);
return epoch;
}

bool MoQOutput::TryGetConnectionStats(ConnectionStats *out)
{
if (!out)
Expand Down
4 changes: 0 additions & 4 deletions cpp/obs/src/moq-output.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ class MoQOutput {
// Prefer this over obs_output_get_connect_time_ms, which stays 0 for sub-ms connects.
bool IsLiveSession();

// Publisher epoch of this Start(), retained through session reconnects; empty when stopped.
std::string GetEpoch();

// Most recent connect/reconnect failure for this Start(), or empty when none.
// Thread-safe; the dock polls this while connecting, while reconnecting, and on stop.
void CopyLastFailure(int *code, std::string *reason);
Expand Down Expand Up @@ -174,7 +171,6 @@ class MoQOutput {
bool connected = false;
bool live = false;
std::string url;
std::string epoch;
int last_failure_code = 0;
std::string last_failure_reason;
std::string token_refusal;
Expand Down
4 changes: 2 additions & 2 deletions cpp/obs/src/moq-source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,7 @@ static bool moq_source_same_video(const Track *track, const std::string &id, con
const bool same_coded =
old.coded.has_value() == config.coded.has_value() &&
(!old.coded || (old.coded->width == config.coded->width && old.coded->height == config.coded->height));
return old.broadcast == config.broadcast && old.epoch == config.epoch && old.codec == config.codec &&
return old.broadcast == config.broadcast && old.instance == config.instance && old.codec == config.codec &&
old.description == config.description && same_coded &&
moq_source_same_container(old.container, config.container);
}
Expand All @@ -953,7 +953,7 @@ static bool moq_source_same_audio(const Track *track, const std::string &id, con
// The same track under a new catalog ID is the same rendition.
if (old.track.value_or(track->id) != config.track.value_or(id))
return false;
return old.broadcast == config.broadcast && old.epoch == config.epoch && old.codec == config.codec &&
return old.broadcast == config.broadcast && old.instance == config.instance && old.codec == config.codec &&
old.description == config.description && old.sample_rate == config.sample_rate &&
old.channel_count == config.channel_count && moq_source_same_container(old.container, config.container);
}
Expand Down
4 changes: 1 addition & 3 deletions cpp/obs/test/moq-audio-encoder-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,7 @@ void CheckSubscriberDecodes(const char *preset, size_t channels)
auto origin = moq::OriginProducer::init(moq::OriginConfig{});
auto publication = TestOk(origin->create_broadcast("room"), "create_broadcast");
auto broadcast = publication->broadcast();
moq::AnnounceRoute route;
route.epoch = moq::mint_epoch();
TestOk(publication->announce(route), "announce");
TestOk(publication->announce({}), "announce");

moq::AudioInit init{};
init.format = moq::AudioFormat::kOpus;
Expand Down
22 changes: 10 additions & 12 deletions cpp/obs/test/moq-output-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ std::optional<moq::Catalog> relayCatalog(const std::shared_ptr<moq::BroadcastCon
// The production commit boundary lets a real stats call race retirement without
// callbacks or branches in the output's hot path.
struct MoQOutputStatsTest {
static std::optional<std::string> Epoch(MoQOutput &output)
static std::optional<std::string> Instance(MoQOutput &output)
{
std::shared_ptr<moq::OriginProducer> origin;
{
Expand All @@ -381,7 +381,9 @@ struct MoQOutputStatsTest {
if (!event)
return std::nullopt;
const auto *start = std::get_if<moq::AnnounceEvent::kStart>(&event->get_variant());
return start ? start->announce.route.epoch : std::nullopt;
if (!start)
return std::nullopt;
return start->announce.route.instance;
}

static std::shared_ptr<moq::Session> Session(MoQOutput &output)
Expand Down Expand Up @@ -457,26 +459,22 @@ int main()
reset(relay.Url());
MoQOutput output(nullptr, OUTPUT);
CHECK(output.Start());
const auto first = MoQOutputStatsTest::Epoch(output);
CHECK(first.has_value());
CHECK(first == output.GetEpoch());
const auto first = MoQOutputStatsTest::Instance(output);
CHECK(first.has_value() && !first->empty());
CHECK(WaitFor([&] { return output.IsLiveSession() && relay.Accepted() == 1; }));
// The plugin names itself ahead of the C++ package, so a relay can tell it apart.
CHECK(relay.Advertised("moq-obs/dev moq-cpp/"));
relay.DropSessions();
CHECK(WaitFor([&] { return output.GetReconnectCount() == 1 && output.IsLiveSession(); }));
CHECK(MoQOutputStatsTest::Epoch(output) == first);
CHECK(first == output.GetEpoch());
CHECK(MoQOutputStatsTest::Instance(output) == first);
output.Stop();
CHECK(output.GetEpoch().empty());
CHECK(output.Start());
const auto second = MoQOutputStatsTest::Epoch(output);
CHECK(second.has_value());
const auto second = MoQOutputStatsTest::Instance(output);
CHECK(second.has_value() && !second->empty());
CHECK(second != first);
CHECK(second == output.GetEpoch());
output.Stop();
}
printf("each start announces a fresh epoch, reconnect preserves it: ok\n");
printf("each start announces a fresh instance, reconnect preserves it: ok\n");

{
TestRelay relay;
Expand Down
22 changes: 11 additions & 11 deletions cpp/obs/test/moq-source-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ int main()
}
report("all-disabled section holds the playing rendition");

// A rendition's publisher epoch is part of its identity, for the active and the pending
// A rendition's stream instance is part of what names it, for the active and the pending
// track alike: a sibling publisher restarting behind a stable catalog resubscribes.
{
TestRelay relay;
Expand All @@ -1364,28 +1364,28 @@ int main()
{
std::lock_guard<std::mutex> lock(ctx->mutex);
const auto &conn = ctx->connection;
snapshot.video.begin()->second.epoch = "01900000-0000-7000-8000-000000000001";
snapshot.audio.begin()->second.epoch = "01900000-0000-7000-8000-000000000001";
snapshot.video.begin()->second.instance = "01900000-0000-7000-8000-000000000001";
snapshot.audio.begin()->second.instance = "01900000-0000-7000-8000-000000000001";
moq_source_subscribe_video(ctx, conn, snapshot);
moq_source_subscribe_audio(ctx, conn, snapshot);
CHECK(conn->pending_video && conn->pending_audio);
const auto pending_video = conn->pending_video;
const auto pending_audio = conn->pending_audio;
// The same epoch keeps the pending track.
// The same instance keeps the pending track.
moq_source_subscribe_video(ctx, conn, snapshot);
moq_source_subscribe_audio(ctx, conn, snapshot);
CHECK(conn->pending_video == pending_video && conn->pending_audio == pending_audio);
// Another epoch replaces it.
snapshot.video.begin()->second.epoch = "01900000-0000-7000-8000-000000000002";
snapshot.audio.begin()->second.epoch = "01900000-0000-7000-8000-000000000002";
// Another instance replaces it.
snapshot.video.begin()->second.instance = "01900000-0000-7000-8000-000000000002";
snapshot.audio.begin()->second.instance = "01900000-0000-7000-8000-000000000002";
moq_source_subscribe_video(ctx, conn, snapshot);
moq_source_subscribe_audio(ctx, conn, snapshot);
CHECK(conn->pending_video && conn->pending_video != pending_video);
CHECK(conn->pending_audio && conn->pending_audio != pending_audio);
}
destroySource(source);
}
report("epoch change resubscribes");
report("instance change resubscribes");

// A new rendition that has not delivered a frame cannot stop the old track.
{
Expand Down Expand Up @@ -1607,7 +1607,7 @@ int main()
if (sibling) {
hidden = TestOk(relay.origin->create_broadcast("obs/hidden"), "unannounced sibling");
config.broadcast = "./hidden";
config.epoch = "01900000-0000-7000-8000-000000000001";
config.instance = "obs-test-pinned";
}
snapshot->video.clear();
snapshot->video.emplace("!unavailable", config);
Expand All @@ -1627,9 +1627,9 @@ int main()
// An unannounced sibling stays pending, without interrupting current playback.
const int frames = g_output_frames;
CHECK(publisher.WriteUntil([&] { return g_output_frames >= frames + 3; }));
// A different publisher instance is a real resolution failure.
// A different stream is a real resolution failure.
moq::AnnounceRoute route;
route.epoch = "01900000-0000-7000-8000-000000000002";
route.instance = "obs-test-other";
TestOk(hidden->announce(route), "announce mismatched sibling");
}
CHECK(WaitFor([] {
Expand Down
14 changes: 7 additions & 7 deletions dart/moq/MIGRATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ the matching generated bindings and native library.

### `announce` takes an `AnnounceRoute`

`BroadcastProducer.announce(route:)` takes `AnnounceRoute(cost:, epoch:)` instead of a `MoqRoute`: the origin builds the hop chain, so `hops` is no longer an input.
`MoqRoute` is only what announcements report. To re-announce an observed route, copy its `cost` and `epoch`.
`BroadcastProducer.announce(route:)` takes `AnnounceRoute(cost:, instance:, epoch:)` instead of a `MoqRoute`: the origin builds the hop chain, so `hops` is no longer an input.
`MoqRoute` is only what announcements report. To re-announce an observed route, copy its `cost`, and its `instance` only when forwarding that same stream; leave `instance` unset to keep the one the broadcast minted.

### Cancelling a stream cancels its pending read

Expand Down Expand Up @@ -117,11 +117,11 @@ moq-transport and moq-lite-03/04 sessions are unchanged.
A container import with `ContainerFormat.fmp4` now publishes one Legacy frame per sample instead of one CMAF frame per fragment.
Pass the new `ContainerFormat.cmaf` to keep publishing CMAF.

### Catalog references carry their epoch
### Catalog references carry their instance

`Video` and `Audio` renditions gain `epoch`, the publisher instance their `broadcast` reference names.
`BroadcastConsumer.resolve(reference:)` becomes `resolve(rendition:)`, taking the catalog `Rendition` and reading its `broadcast` and `epoch` from it.
Resolving, and the rendition-based consumers, throw for a rendition whose broadcast is proven to serve another epoch.
`Video` and `Audio` renditions gain `instance`, the publisher instance their `broadcast` reference names.
`BroadcastConsumer.resolve(reference:)` becomes `resolve(rendition:)`, taking the catalog `Rendition` and reading its `broadcast` and `instance` from it.
Resolving, and the rendition-based consumers, throw for a rendition whose broadcast is proven to serve another instance.

### Timestamps stop at 2^61 - 1 microseconds (#6168)

Expand All @@ -137,7 +137,7 @@ Publish a replacement under a new name, and expect a finished track's demand wat
### A claim answers by publishing (#5678)

`origin.dynamic_(prefix:)` takes no route, and `update` is gone.
Replace `request.accept(broadcast:)` with `request.prepare(epoch: mintEpoch())`, which returns a `BroadcastPrepared`: fill its `broadcast()`, then `publish()` announces it at the exact path under that epoch and returns its producer.
Replace `request.accept(broadcast:)` with `request.prepare()`, which returns a `BroadcastPrepared`: fill its `broadcast()`, then `publish()` announces it at the exact path under a fresh instance of its own and returns its producer.

### Anchors can name a time (#6074)

Expand Down
1 change: 0 additions & 1 deletion dart/moq/lib/moq.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ export 'package:moq_ffi/moq_ffi.dart';

export 'src/aliases.dart';
export 'src/client.dart';
export 'src/epoch.dart';
export 'src/server.dart';
export 'src/timestamp.dart';
2 changes: 1 addition & 1 deletion dart/moq/lib/src/aliases.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ typedef AnnounceConfig = MoqAnnounceConfig;
/// Follows a specific broadcast path across the publisher instances that serve it.
typedef Following = MoqFollowing;

/// How a broadcast advertises its exact path: its static production cost and publisher epoch.
/// How a broadcast advertises its exact path: its static production cost and stream instance.
typedef AnnounceRoute = MoqAnnounceRoute;

/// A route over a prefix: its origin-relative path, required wildcard captures (empty without wildcards), and route metadata.
Expand Down
14 changes: 7 additions & 7 deletions dart/moq/lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,15 @@ final class Moq {
}) => session.consume().announced(config: options._ffi);

/// Follow the broadcast at exactly [path]: each `available()` resolves the
/// next publisher instance serving it, such as a restarted publisher. Pass an
/// [epoch] (UUIDv7 text) to follow only that instance.
Following follow(String path, {String? epoch}) =>
session.consume().follow(path: path, epoch: epoch);
/// next instance serving it, such as a restarted publisher. Pass an
/// [instance] to follow only that stream.
Following follow(String path, {String? instance}) =>
session.consume().follow(path: path, instance: instance);

/// Resolve one publisher instance of the broadcast at [path]. Pass an
/// [epoch] (UUIDv7 text) to refuse any other instance.
Future<BroadcastConsumer> request(String path, {String? epoch}) =>
session.consume().request(path: path, epoch: epoch);
/// [instance] to refuse any other stream.
Future<BroadcastConsumer> request(String path, {String? instance}) =>
session.consume().request(path: path, instance: instance);

/// The session's bandwidth allocator.
///
Expand Down
7 changes: 0 additions & 7 deletions dart/moq/lib/src/epoch.dart

This file was deleted.

Loading
Loading