Softalleys.Utilities.Events.Distributed.GooglePubSub
1.0.0
dotnet add package Softalleys.Utilities.Events.Distributed.GooglePubSub --version 1.0.0
NuGet\Install-Package Softalleys.Utilities.Events.Distributed.GooglePubSub -Version 1.0.0
<PackageReference Include="Softalleys.Utilities.Events.Distributed.GooglePubSub" Version="1.0.0" />
<PackageVersion Include="Softalleys.Utilities.Events.Distributed.GooglePubSub" Version="1.0.0" />
<PackageReference Include="Softalleys.Utilities.Events.Distributed.GooglePubSub" />
paket add Softalleys.Utilities.Events.Distributed.GooglePubSub --version 1.0.0
#r "nuget: Softalleys.Utilities.Events.Distributed.GooglePubSub, 1.0.0"
#:package Softalleys.Utilities.Events.Distributed.GooglePubSub@1.0.0
#addin nuget:?package=Softalleys.Utilities.Events.Distributed.GooglePubSub&version=1.0.0
#tool nuget:?package=Softalleys.Utilities.Events.Distributed.GooglePubSub&version=1.0.0
Softalleys.Utilities.Events.Distributed.GooglePubSub
Google Cloud Pub/Sub transport for Softalleys.Utilities.Events.Distributed with both delivery modes supported:
- Push: Pub/Sub sends HTTP POST requests to your service (Minimal API endpoint provided)
- Pull: Your service runs a background subscriber that pulls and processes messages
This package aims to give you an out‑of‑the‑box event-driven integration with minimal application code: configure once and handle your events.
What is Google Cloud Pub/Sub (quick intro)
Google Cloud Pub/Sub is a fully-managed messaging service that implements pub/sub semantics:
- Producers publish messages to a topic
- One or many subscriptions are attached to a topic
- Each subscription delivers messages to a consumer (push via HTTP or pull via client)
- Delivery is at-least-once; your handlers should be idempotent
Fan-out is modeled by creating multiple subscriptions on the same topic (one push endpoint per subscription).
Why Softalleys.Utilities.Events + Pub/Sub
Softalleys.Utilities.Events gives you a clean event-driven developer experience:
- Strongly-typed events and handlers
- Clear naming and versioning
- Pluggable distributed transports
With this package you can emit and receive those events over Google Pub/Sub with almost no glue code.
Features
- Publish events to a configured Pub/Sub topic
- Receive events via:
- Push (HTTP POST to a Minimal API endpoint you map)
- Pull (BackgroundService that streams messages)
- Configurable naming and serialization (inherits from the base distributed events builder)
- JWT/OIDC validation for push requests (enable in production; disable for emulator)
- Dev-friendly options for emulator and local setups
Installation
Add the package reference to your project:
<ItemGroup>
<PackageReference Include="Softalleys.Utilities.Events.Distributed.GooglePubSub" Version="x.y.z" />
<PackageReference Include="Softalleys.Utilities.Events" Version="x.y.z" />
<PackageReference Include="Softalleys.Utilities.Events.Distributed" Version="x.y.z" />
</ItemGroup>
Quick start: minimal Sender (Ping)
Program.cs:
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Softalleys.Utilities.Events;
using Softalleys.Utilities.Events.Distributed.Configuration;
using Softalleys.Utilities.Events.Distributed.GooglePubSub;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddSoftalleysEvents(typeof(PingRequested).Assembly)
.AddDistributedEvents(dist =>
{
dist.Emit.AllEvents();
dist.Emit.RequireDistributedSuccess(); // wait for publish completion (useful for console apps)
dist.Serialization.UseSystemTextJson();
dist.Naming.UseKebabCase().Map<PingRequested>("ping-requested", 1);
dist.UseGooglePubSub(g => g.Configure(o =>
{
o.ProjectId = "local-project"; // or your GCP project
o.TopicId = "events";
// Local emulator convenience: topic will be auto-created on first publish by the publisher
// In production, provision topic/subscriptions with IaC (Terraform, gcloud, etc.)
}));
});
var app = builder.Build();
await using var scope = app.Services.CreateAsyncScope();
var bus = scope.ServiceProvider.GetRequiredService<IEventBus>();
await bus.PublishAsync(new PingRequested { Message = "hello from ping" });
Notes:
- No Pub/Sub admin code is needed in your app; the transport handles publishing.
- For the emulator, set
PUBSUB_EMULATOR_HOSTto point to the emulator host.
Quick start: minimal Receiver (Pong) via Push
Program.cs (Minimal API):
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Softalleys.Utilities.Events;
using Softalleys.Utilities.Events.Distributed.Configuration;
using Softalleys.Utilities.Events.Distributed.GooglePubSub;
using Softalleys.Utilities.Events.Distributed.GooglePubSub.Receiving;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddSoftalleysEvents(typeof(PingRequested).Assembly)
.AddDistributedEvents(dist =>
{
dist.Serialization.UseSystemTextJson();
dist.Naming.UseKebabCase().Map<PingRequested>("ping-requested", 1);
dist.UseGooglePubSub(g => g.Configure(o =>
{
o.ProjectId = "local-project";
o.TopicId = "events";
// Push receiver security:
// In production: keep RequireJwtValidation = true and set Audience/Issuer
// For local emulator: set RequireJwtValidation = false (no token is sent)
o.RequireJwtValidation = false; // emulator/dev only
// Optional: customize the endpoint path
// o.SubscribePath = "/google-pubsub/receive";
}));
});
builder.Services.AddScoped<IEventHandler<PingRequested>, PingRequestedHandler>();
var app = builder.Build();
// Expose the push endpoint. Pub/Sub will POST here.
app.MapGooglePubSubReceiver();
// Health
app.MapGet("/health", () => Results.Ok("ok"));
await app.RunAsync();
public sealed class PingRequestedHandler : IEventHandler<PingRequested>
{
public Task HandleAsync(PingRequested e, CancellationToken ct = default)
{
Console.WriteLine($"[PONG] Received: {e.Message}");
return Task.CompletedTask;
}
}
To receive messages, create a push subscription on your topic that targets the service URL + SubscribePath.
Important:
- A push subscription has a single
PushEndpoint. To fan out to multiple services, create multiple subscriptions. - In production, use HTTPS and OIDC tokens. Validate:
- Issuer:
https://accounts.google.com - Audience: your Cloud Run service URL (or configured audience)
- Issuer:
Quick start: minimal Receiver (Pong) via Pull
Program.cs (Generic Host or Web):
builder.Services
.AddSoftalleysEvents(typeof(PingRequested).Assembly)
.AddDistributedEvents(dist =>
{
dist.Serialization.UseSystemTextJson();
dist.Naming.UseKebabCase().Map<PingRequested>("ping-requested", 1);
dist.UseGooglePubSub(g => g.Configure(o =>
{
o.ProjectId = "local-project";
o.TopicId = "events";
// Pull mode
o.EnablePullSubscriber = true;
o.SubscriptionId = "pong-sub"; // existing subscription (create via IaC)
// Dev convenience (emulator only):
// o.AutoProvisionSubscription = true; // creates the pull subscription if missing
}));
});
The package hosts a background pull subscriber that streams messages and dispatches to your IEventHandler<TEvent>.
Configuration
Configuration section: Softalleys:Events:Distributed:GooglePubSub
Common keys:
ProjectId(string): GCP project idTopicId(string): Pub/Sub topic (defaultevents)SubscribePath(string): Minimal API path for push (default/google-pubsub/receive)SubscriptionId(string): subscription name (required for pull; used by tooling/provisioning)RequireJwtValidation(bool, default true): validate Bearer token on push requestsAudience(string): expected audience for JWTIssuer(string): expected issuer for JWT (e.g.,https://accounts.google.com)JwksEndpoint(string): optional JWKS if using custom issuerEnablePullSubscriber(bool): enable/disable pull subscriber background serviceAutoProvisionTopic(bool): dev convenience; topic is already ensured on publishAutoProvisionSubscription(bool): dev convenience for pull; create sub if missingPushEndpoint(string): target URL when provisioning a push subscription (dev/emulator)AckDeadlineSeconds(int): ack deadline used when creating subscriptions (dev)
Environment variables mapping uses __ as separator, for example:
Softalleys__Events__Distributed__GooglePubSub__ProjectId=local-project
Softalleys__Events__Distributed__GooglePubSub__TopicId=events
Softalleys__Events__Distributed__GooglePubSub__SubscriptionId=pong-sub
Softalleys__Events__Distributed__GooglePubSub__EnablePullSubscriber=true
Emulator:
- Set
PUBSUB_EMULATOR_HOST=host:portto make clients use the emulator. - For push in Docker,
PushEndpointtypically points to another container by name (e.g.,http://pong:5187/google-pubsub/receive).
Cloud Run guidance (production)
- Prefer push subscriptions (or Eventarc Pub/Sub triggers) for Cloud Run; it aligns with request-driven scaling.
- Use HTTPS endpoints and OIDC tokens:
- Configure the push subscription with a service account that has
Cloud Run Invokeron your service - Validate JWT: Issuer
https://accounts.google.com; Audience your Cloud Run URL
- Configure the push subscription with a service account that has
- Make handlers idempotent; Pub/Sub is at-least-once
- Use Dead Letter Queues and retry policies on the subscription for poison messages
- Provision topics/subscriptions with IaC; keep auto-provision flags off in production
Pull mode on Cloud Run is possible but less common; you’ll manage lifecycle and scaling carefully. Consider GKE/GCE for long-lived pull workers.
FAQ
Q: Can a subscription push to multiple endpoints?
- No. One push endpoint per subscription. Use multiple subscriptions to fan-out.
Q: Does the library auto-provision resources?
- Topic existence is ensured by the publisher on first publish (helpful for emulator/dev).
- Pull subscriptions can be auto-created if
EnablePullSubscriber=trueandAutoProvisionSubscription=true. - Push subscriptions are typically created with IaC or tooling; configure
PushEndpointonly for dev/emulator flows when you create them yourself.
Q: How do I map event names to types?
- Use
dist.Naming.UseKebabCase().Map<YourEvent>("your-event", version)when configuring the distributed events builder.
End-to-end flow recap
- Sender publishes a strongly-typed event via
IEventBus. - Transport serializes and publishes to Pub/Sub topic.
- Receiver gets the event by:
- Push: Pub/Sub POSTs to
SubscribePath, receiver validates auth (prod) and processes. - Pull: Background subscriber pulls and dispatches to your handler.
- Push: Pub/Sub POSTs to
- Handler executes business logic; on success the message is acked (push: 2xx; pull: Ack).
Happy shipping event-driven services on Pub/Sub!
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net8.0
- Google.Cloud.PubSub.V1 (>= 3.27.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Softalleys.Utilities.Events (>= 1.1.1)
- Softalleys.Utilities.Events.Distributed (>= 1.0.1)
- System.IdentityModel.Tokens.Jwt (>= 7.7.1)
-
net9.0
- Google.Cloud.PubSub.V1 (>= 3.27.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.9)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Softalleys.Utilities.Events (>= 1.1.1)
- Softalleys.Utilities.Events.Distributed (>= 1.0.1)
- System.IdentityModel.Tokens.Jwt (>= 7.7.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 181 | 9/21/2025 |