Google Cloud Pub/Sub integration for ABP Framework's distributed event bus.
This package provides an implementation of ABP's IDistributedEventBus using Google Cloud Pub/Sub as the message broker. It follows the same patterns as the official ABP RabbitMQ and Azure Service Bus integrations.
abp add-package Bdaya.Abp.EventBus.PubSubInstall the NuGet package:
dotnet add package Bdaya.Abp.EventBus.PubSubAdd the module dependency to your ABP module:
[DependsOn(typeof(AbpEventBusPubSubModule))]
public class YourModule : AbpModule
{
// ...
}{
"PubSub": {
"Connections": {
"Default": {
"ProjectId": "your-gcp-project-id",
"CredentialsPath": "/path/to/service-account.json"
}
},
"EventBus": {
"TopicId": "your-events-topic",
"SubscriptionId": "your-app-subscription",
"AutoCreateTopic": true,
"AutoCreateSubscription": true
}
}
}| Property | Description |
|---|---|
Connections |
Dictionary of named connection configurations |
Default |
Shortcut to access Connections["Default"] |
| Property | Description |
|---|---|
ProjectId |
Google Cloud Project ID (required) |
Credential |
Pre-configured GoogleCredential instance (highest priority) |
CredentialsJson |
JSON string with service account credentials |
CredentialsPath |
Path to service account JSON file |
EmulatorHost |
Pub/Sub emulator host for local development (e.g., localhost:8085) |
This package supports multiple authentication methods following Google Cloud best practices. Methods are evaluated in priority order - the first one configured will be used.
| Priority | Method | Property | Best For |
|---|---|---|---|
| 1 | Pre-configured Credential | Credential |
Workload Identity Federation, custom auth flows |
| 2 | JSON String | CredentialsJson |
Secret managers (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault) |
| 3 | Credentials File | CredentialsPath |
Local development, legacy systems |
| 4 | Application Default Credentials | (none - automatic) | GCE, GKE, Cloud Run, Cloud Functions |
| 5 | Emulator | EmulatorHost |
Local development and testing |
When running on Google Cloud (GCE, GKE, Cloud Run, Cloud Functions), ADC automatically uses the attached service account. No configuration needed:
Configure<AbpPubSubOptions>(options =>
{
options.Connections["Default"] = new PubSubConnectionConfiguration
{
ProjectId = "your-project-id"
// No credentials specified - uses ADC automatically
};
});For local development with ADC:
gcloud auth application-default loginLoad credentials from any secret manager:
// Azure Key Vault example
var secretClient = new SecretClient(new Uri("https://your-vault.vault.azure.net/"), new DefaultAzureCredential());
var secret = await secretClient.GetSecretAsync("gcp-service-account");
Configure<AbpPubSubOptions>(options =>
{
options.Connections["Default"] = new PubSubConnectionConfiguration
{
ProjectId = "your-project-id",
CredentialsJson = secret.Value.Value // JSON string from secret
};
});Maximum flexibility for advanced scenarios:
// Workload Identity Federation
var credential = GoogleCredential.FromFile("client-config.json")
.CreateScoped(PublisherServiceApiClient.DefaultScopes);
Configure<AbpPubSubOptions>(options =>
{
options.Connections["Default"] = new PubSubConnectionConfiguration
{
ProjectId = "your-project-id",
Credential = credential
};
});For legacy systems or local development:
Configure<AbpPubSubOptions>(options =>
{
options.Connections["Default"] = new PubSubConnectionConfiguration
{
ProjectId = "your-project-id",
CredentialsPath = "/path/to/service-account.json"
};
});
⚠️ Security Warning: Service account key files are long-lived credentials. Prefer ADC, Workload Identity, or secret managers in production.
Configure<AbpPubSubOptions>(options =>
{
options.Connections["Default"] = new PubSubConnectionConfiguration
{
ProjectId = "test-project", // Any project ID works with emulator
EmulatorHost = "localhost:8085"
};
});These methods require you to create a GoogleCredential and pass it via the Credential property:
| Method | How to Use |
|---|---|
| Workload Identity (GKE) | Automatic via ADC when configured on the cluster |
| Workload Identity Federation | Create credential from config file and pass to Credential |
| Impersonation | Use GoogleCredential.Impersonate() and pass to Credential |
| OAuth 2.0 User Credentials | Create via GoogleWebAuthorizationBroker and pass to Credential |
Example for Workload Identity Federation:
// workforce-config.json contains the federation configuration
var credential = GoogleCredential
.FromFile("workforce-config.json")
.CreateScoped(PublisherServiceApiClient.DefaultScopes);
Configure<AbpPubSubOptions>(options =>
{
options.Connections["Default"] = new PubSubConnectionConfiguration
{
ProjectId = "your-project-id",
Credential = credential
};
});| Property | Default | Description |
|---|---|---|
ConnectionName |
null |
Named connection to use (uses "Default" if not set) |
TopicId |
- | Topic ID for publishing events (required) |
SubscriptionId |
- | Subscription ID for receiving events (required) |
MaxMessages |
10 |
Number of messages to pull in a batch |
AckDeadlineSeconds |
60 |
Message acknowledgment deadline |
AutoCreateTopic |
true |
Auto-create topic if it doesn't exist |
AutoCreateSubscription |
true |
Auto-create subscription if it doesn't exist |
DefaultMessageAttributes |
{} |
Attributes to add to all published messages |
SubscriptionFilter |
null |
Pub/Sub filter expression |
MaxConcurrentHandlers |
1 |
Maximum concurrent message handlers |
EnableMessageOrdering |
false |
Enable message ordering by key |
DeadLetterTopicId |
null |
Dead letter topic for failed messages |
MaxDeliveryAttempts |
5 |
Max delivery attempts before dead letter |
MessageRetentionDays |
7 |
Message retention duration |
You can also configure options in code:
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpPubSubOptions>(options =>
{
options.Connections.Default.ProjectId = "my-project";
options.Connections.Default.CredentialsPath = "/path/to/credentials.json";
});
Configure<AbpPubSubEventBusOptions>(options =>
{
options.TopicId = "distributed-events";
options.SubscriptionId = "my-service-subscription";
options.MaxConcurrentHandlers = 5;
});
}public class MyService : ITransientDependency
{
private readonly IDistributedEventBus _distributedEventBus;
public MyService(IDistributedEventBus distributedEventBus)
{
_distributedEventBus = distributedEventBus;
}
public async Task DoSomethingAsync()
{
await _distributedEventBus.PublishAsync(
new OrderCreatedEto
{
OrderId = Guid.NewGuid(),
Amount = 100.00m
}
);
}
}public class OrderCreatedHandler : IDistributedEventHandler<OrderCreatedEto>, ITransientDependency
{
public async Task HandleEventAsync(OrderCreatedEto eventData)
{
// Handle the event
Console.WriteLine($"Order created: {eventData.OrderId}");
}
}[EventName("Order.Created")]
public class OrderCreatedEto
{
public Guid OrderId { get; set; }
public decimal Amount { get; set; }
}For local development, you can use the Google Cloud Pub/Sub emulator:
Start the emulator:
gcloud beta emulators pubsub start --project=test-projectConfigure your app to use the emulator:
{
"PubSub": {
"Connections": {
"Default": {
"ProjectId": "test-project",
"EmulatorHost": "localhost:8085"
}
},
"EventBus": {
"TopicId": "test-events",
"SubscriptionId": "test-subscription"
}
}
}The package supports three authentication methods:
-
Application Default Credentials (ADC) - Recommended for production
- Uses
GOOGLE_APPLICATION_CREDENTIALSenvironment variable - Automatically works with GKE Workload Identity
- Works with Cloud Run, Cloud Functions, etc.
- Uses
-
Service Account JSON File
- Set
CredentialsPathin connection configuration - Useful for local development or non-GCP environments
- Set
-
Emulator
- Set
EmulatorHostin connection configuration - No authentication required
- Set
You can define multiple connections for different Pub/Sub projects:
{
"PubSub": {
"Connections": {
"Default": {
"ProjectId": "project-1"
},
"Analytics": {
"ProjectId": "analytics-project"
}
},
"EventBus": {
"ConnectionName": "Analytics",
"TopicId": "analytics-events",
"SubscriptionId": "my-app"
}
}
}This implementation supports ABP's outbox/inbox pattern for reliable event delivery. Configure your outbox/inbox as documented in the ABP Framework documentation.
| Feature | RabbitMQ | Azure Service Bus | Pub/Sub |
|---|---|---|---|
| Exchange/Topic | ✓ | ✓ | ✓ (Topic) |
| Queue/Subscription | ✓ | ✓ | ✓ (Subscription) |
| Dead Letter | ✓ | ✓ | ✓ |
| Message Ordering | Limited | ✓ | ✓ (with ordering key) |
| Filtering | Routing Key | SQL Filter | Filter Expression |
| Auto-scaling | Manual | ✓ | ✓ |
This package is licensed under the same license as the parent project.