Verbara.Sdk.Push 2.8.0

dotnet add package Verbara.Sdk.Push --version 2.8.0
                    
NuGet\Install-Package Verbara.Sdk.Push -Version 2.8.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Verbara.Sdk.Push" Version="2.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Verbara.Sdk.Push" Version="2.8.0" />
                    
Directory.Packages.props
<PackageReference Include="Verbara.Sdk.Push" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Verbara.Sdk.Push --version 2.8.0
                    
#r "nuget: Verbara.Sdk.Push, 2.8.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Verbara.Sdk.Push@2.8.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Verbara.Sdk.Push&version=2.8.0
                    
Install as a Cake Addin
#tool nuget:?package=Verbara.Sdk.Push&version=2.8.0
                    
Install as a Cake Tool

Verbara.Sdk.Push

Real-time push primitives for .NET. AOT-safe, host-agnostic, MIT licensed.

What it does

  • Typed, in-memory event bus (IPushEventBus) backed by a bounded System.Threading.Channels.Channel<T> with configurable backpressure.
  • Delivery filter (IEventDeliveryFilter) that enforces tenant isolation and optional per-user targeting before an event reaches a subscriber.
  • Subscription registry (ISubscriptionRegistry) for tracking active subscribers per tenant with automatic cleanup on disposal.
  • First-class diagnostics via System.Diagnostics.Metrics (meter name Verbara.Sdk.Push).

No ASP.NET Core dependency. No reflection. Trim-safe.

Install

dotnet add package Verbara.Sdk.Push

Quick start

using Verbara.Sdk.Push.Bus;
using Verbara.Sdk.Push.Delivery;
using Verbara.Sdk.Push.Events;
using Verbara.Sdk.Push.Hosting;
using Verbara.Sdk.Push.Subscriptions;
using Microsoft.Extensions.DependencyInjection;

// 1) Define a concrete event
public sealed record ConversationAssigned : PushEvent
{
    public required string ConversationId { get; init; }
    public override string EventType => "conversation.assigned";
}

// 2) Register services
var services = new ServiceCollection();
services.AddLogging();
services.AddVerbaraPush(options =>
{
    options.BufferCapacity = 512;
    options.BackpressureStrategy = BackpressureStrategy.DropOldest;
});

using var sp = services.BuildServiceProvider();
var bus      = sp.GetRequiredService<IPushEventBus>();
var filter   = sp.GetRequiredService<IEventDeliveryFilter>();
var registry = sp.GetRequiredService<ISubscriptionRegistry>();

// 3) Register a subscriber and subscribe to a typed stream
var subscriber = new SubscriberContext(
    TenantId:    "tenant-1",
    UserId:      "user-42",
    Roles:       new HashSet<string> { "agent" },
    Permissions: new HashSet<string> { "conversation:read" });

using var _registration = registry.Register(subscriber);

using var subscription = bus.OfType<ConversationAssigned>().Subscribe(evt =>
{
    if (filter.IsDeliverableToSubscriber(evt, subscriber))
    {
        Console.WriteLine($"{evt.EventType}: {evt.ConversationId}");
    }
});

// 4) Publish
await bus.PublishAsync(new ConversationAssigned
{
    ConversationId = "c-123",
    Metadata = new PushEventMetadata(
        TenantId:      "tenant-1",
        UserId:        "user-42",
        OccurredAt:    DateTimeOffset.UtcNow,
        CorrelationId: null),
});

Contract

PushEventBusOptions

Setting Default Description
BufferCapacity 256 Max in-flight events before the backpressure strategy kicks in. Must be >= 1.
BackpressureStrategy DropOldest Behavior when the buffer is full.

BackpressureStrategy

  • DropOldest (default) — evict the oldest buffered event to make room for the new one. Favors freshness; appropriate for live UI streams where stale events are worthless.
  • DropNewest — evict the most recently buffered event to admit the new one (the BCL DropNewest mode). The oldest buffered events survive; the event being published is always enqueued.
  • Block — await buffer space. Use only when publishers can tolerate backpressure (batch pipelines, not hot request paths).

Every event a full buffer evicts under DropOldest or DropNewest increments asterisk.push.events.dropped once, tagged reason="buffer_full"; Block never evicts. A publish that races the bus's disposal is counted with reason="writer_closed".

Observability

The package exposes a System.Diagnostics.Metrics.Meter named Verbara.Sdk.Push with the following instruments:

Instrument Kind Description
asterisk.push.events.published Counter<long> Events accepted by PublishAsync.
asterisk.push.events.delivered Counter<long> Events dispatched to at least one observer.
asterisk.push.events.dropped Counter<long> Events discarded (tag: reason=buffer_full\|writer_closed).
asterisk.push.sse.events.dropped Counter<long> Event frames an SSE connection of Verbara.Sdk.Push.AspNetCore dropped at its per-connection bound (each reported to that client in a .gap frame).
asterisk.push.subscribers.active ObservableGauge<int> Current active subscriptions (bound via PushMetrics.BindActiveSubscribersGauge).

Wire into OpenTelemetry with meterProvider.AddMeter("Verbara.Sdk.Push").

Tracing

The bus also starts spans on an ActivitySource named Verbara.Sdk.Push; register it with tracerProvider.AddSource("Verbara.Sdk.Push").

  • Publish. PublishAsync starts push publish <eventType> (Producer) under the publisher's current activity, and records that activity's W3C traceparent in the event's Metadata.TraceContext when the publisher left it empty. A TraceContext the publisher set explicitly is kept as it is.

  • Deliver. The dispatch loop starts push deliver <eventType> (Internal) as a child of the event's TraceContext. Every span a subscriber starts while handling the event — a webhook POST's HTTP client span, a NATS publish — is therefore in the publisher's trace, and the traceparent written on the wire (HTTP header, NATS header) belongs to that trace:

    api.handler (your activity)
    ├── push publish order.created
    └── push deliver order.created
        └── subscriber spans (HTTP POST, NATS publish, …)
    
  • Root case. An event with no TraceContext, or one that does not parse as a W3C traceparent, is delivered under a root push deliver span, as before; the event is never dropped for it.

  • Who built the bus does not matter. The dispatch loop starts without the constructing code's ambient activity, so a bus first resolved inside a host start-up span or inside the first HTTP request never puts later deliveries in that trace.

  • Sampling. Because the delivery is now a child of the publisher's span, a parent-based sampler makes the delivery (and the subscriber spans inside it) follow the publisher's sampling decision instead of deciding afresh at a root.

  • Cost. With no listener on the source, no span is started and the trace context is not parsed.

AOT

This package is Native AOT compatible. The shipping build verifies zero trim warnings (IL2026 / IL2070 / IL2075 / IL3050 / ...) via the repo's AotCanary publish (tools/verify-aot.sh). No reflection, no DataAnnotations runtime validator, no dynamic code.

Relation with Verbara.Sdk.Pro.Push

This package provides in-memory primitives suitable for single-node hosts. For NATS-backed multi-node fan-out in the MIT surface, see Verbara.Sdk.Push.Nats (available since v1.12). For cluster-wide fan-out over Redis pub/sub or Postgres LISTEN/NOTIFY backplanes (neither stores events for replay), advanced authorization, and enterprise observability, see Verbara.Sdk.Pro.Push — both build on top of this package's abstractions, so the contract is forward-compatible.

Licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Verbara.Sdk.Push:

Package Downloads
Verbara.Sdk.Push.Webhooks

Verbara.Sdk.Push.Webhooks - outbound HTTP webhook delivery for Verbara.Sdk.Push. Consumes events from the Push bus, matches against WebhookSubscription topic patterns, POSTs with HMAC-SHA256 signature and exponential retry/backoff. AOT-safe.

Verbara.Sdk.Push.Nats

Verbara.Sdk.Push.Nats - publishes Push bus events to a NATS subject hierarchy that mirrors the Push topic tree (asterisk.sdk.**). AOT-safe.

Verbara.Sdk.Push.AspNetCore

Verbara.Sdk.Push.AspNetCore - SSE push delivery endpoints for ASP.NET Core. Maps IPushEventBus events to Server-Sent Events with topic filtering and JWT authorization.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.8.0 84 10/9/2026
2.7.0 763 10/3/2026
2.6.1 486 9/30/2026
2.6.0 723 9/24/2026
2.5.3 626 9/13/2026
2.5.2 285 9/13/2026
2.5.1 279 9/12/2026
2.5.0 163 8/25/2026
2.4.0 1,920 7/27/2026
2.3.2 686 7/20/2026
2.3.1 334 7/14/2026
2.3.0 391 7/6/2026
2.2.1 970 5/23/2026
2.2.0 183 5/20/2026
2.1.2 169 5/8/2026
2.1.1 155 5/7/2026
2.1.0 152 5/7/2026
2.0.0 160 5/6/2026