ServiceMq.SharpCoreDb
7.4.0
dotnet add package ServiceMq.SharpCoreDb --version 7.4.0
NuGet\Install-Package ServiceMq.SharpCoreDb -Version 7.4.0
<PackageReference Include="ServiceMq.SharpCoreDb" Version="7.4.0" />
<PackageVersion Include="ServiceMq.SharpCoreDb" Version="7.4.0" />
<PackageReference Include="ServiceMq.SharpCoreDb" />
paket add ServiceMq.SharpCoreDb --version 7.4.0
#r "nuget: ServiceMq.SharpCoreDb, 7.4.0"
#:package ServiceMq.SharpCoreDb@7.4.0
#addin nuget:?package=ServiceMq.SharpCoreDb&version=7.4.0
#tool nuget:?package=ServiceMq.SharpCoreDb&version=7.4.0
ServiceMq
A durable, store-and-forward message queue for .NET
ServiceMq moves typed objects, text, or bytes between .NET processes over named pipes or TCP. A sender writes each message to durable storage before delivery. If the destination is unavailable, ServiceMq retries without making the application manage a retry loop. A receiver can consume immediately or explicitly acknowledge work.
Documentation
The ServiceMq User Guide is the main documentation. Start with:
| If you want to… | Read |
|---|---|
| Send and receive a message in ten minutes | Getting started |
| Choose named pipes, TCP, or both | Addresses and transports |
Understand Receive, Accept, and delivery guarantees |
Messages and delivery |
| Choose file, memory, SQLite, or custom storage | Storage |
| Configure retries and recover failed messages | Retries and dead letters |
| Monitor disk use and repair bad records | Operations |
| Protect data and deploy safely | Security |
| Upgrade an older ServiceMq application | Migrating to 7.0 |
Use the non-blocking async API |
Async API |
| Diagnose a problem | Troubleshooting |
Install
dotnet add package ServiceMq --version 7.4.0
For SQLite storage:
dotnet add package ServiceMq.Sqlite --version 7.4.0
For SharpCoreDB storage (requires .NET 10):
dotnet add package ServiceMq.SharpCoreDb --version 7.4.0
ServiceMq and ServiceMq.Sqlite target netstandard2.0 and net8.0; ServiceMq.SharpCoreDb targets net10.0 only. ServiceMq 7 uses ServiceWire 7.0.
Quick start
Create one address and queue per process. This example uses named pipes because both queues are on the same machine:
using ServiceMq;
var ordersAddress = new Address("orders-pipe");
using var orders = new MessageQueue(
name: "orders",
address: ordersAddress,
msgDir: @"C:\service-data\orders");
using var checkout = new MessageQueue(
name: "checkout",
address: new Address("checkout-pipe"),
msgDir: @"C:\service-data\checkout");
Guid id = checkout.Send(ordersAddress, new OrderPlaced
{
OrderId = 42,
Total = 19.95m
});
Message message = orders.Receive(timeoutMs: 5_000);
if (message != null)
{
OrderPlaced order = message.To<OrderPlaced>();
Console.WriteLine($"Received {message.Id}: order {order.OrderId}");
}
public sealed class OrderPlaced
{
public int OrderId { get; set; }
public decimal Total { get; set; }
}
Send returns after the outgoing message is stored, not necessarily delivered.
Receive removes the incoming record before returning it. Use Accept followed by
Acknowledge when work must remain recoverable until processing finishes:
Message message = orders.Accept(timeoutMs: 5_000);
if (message != null)
{
try
{
await HandleOrder(message.To<OrderPlaced>());
orders.Acknowledge(message);
}
catch
{
orders.ReEnqueue(message);
throw;
}
}
Production configuration
The original constructor remains supported. MessageQueueOptions exposes the complete
configuration surface:
var queue = new MessageQueue(new MessageQueueOptions
{
Name = "orders",
Address = new Address("orders-pipe"),
VisibilityTimeout = TimeSpan.FromMinutes(1),
Storage = new StorageOptions
{
RootPath = @"D:\service-data\orders",
Durability = DurabilityMode.FlushToDisk,
MaxBytes = 10L * 1024 * 1024 * 1024,
MaxMessages = 1_000_000,
FullBehavior = QueueFullBehavior.Reject,
SentRetention = TimeSpan.FromDays(2),
ReadRetention = TimeSpan.FromHours(12),
DeadLetterRetention = TimeSpan.FromDays(30),
SentAuditPayload = AuditPayloadMode.MetadataOnly,
ReadAuditPayload = AuditPayloadMode.MetadataOnly
},
Delivery = new DeliveryOptions
{
MaxConcurrentDestinations = 8,
MaxAttempts = 100,
MaxAge = TimeSpan.FromDays(1),
InitialRetryDelay = TimeSpan.FromSeconds(1),
MaximumRetryDelay = TimeSpan.FromMinutes(1),
RetryBackoffFactor = 1.5
}
});
See Storage for every option and provider.
What ServiceMq guarantees
- Outgoing and incoming records are stored before their respective RPC calls return.
- Delivery is at least once. A crash in the final acknowledgment window can produce
a duplicate, so consumers should treat
Message.Idas an idempotency key. - Messages sent by one
MessageQueueare delivered FIFO per destination, including after an outage or restart. Concurrent sends are ordered when they enter the durable outbound queue; ordering does not span separate sender processes. - File records use atomic replacement and malformed records are quarantined.
- Legacy
.omqand.imqrecords remain readable.
ServiceMq is an embedded queue library, not a clustered broker. It does not provide distributed consensus, competing-consumer coordination across several processes, or exactly-once side effects.
Storage providers
| Provider | Package | Best for |
|---|---|---|
FileMessageStore |
ServiceMq |
Durable queues with minimal infrastructure |
MemoryMessageStore |
ServiceMq |
Tests and deliberately transient queues |
SqliteMessageStore |
ServiceMq.Sqlite |
Indexed, transactional storage in one database file |
IMessageStore |
Your assembly | Application-specific storage engines |
Project status
See the 7.4.0 release notes for async reliability fixes.
ServiceMq 7.0 targets .NET Standard 2.0 and .NET 8.0 and uses ServiceWire 7.0. The test suite covers named pipes, TCP, restart compatibility, capacity policies, visibility timeouts, dead-letter replay, encryption, corruption quarantine, and all built-in storage providers.
Licensed under the Apache License 2.0.
| Product | Versions 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. |
-
net10.0
- ServiceMq (>= 7.4.0)
- SharpCoreDB (>= 2.0.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
7.4.0: fixes async receive cancellation losing unreturned messages, preserves acknowledgement visibility leases until completion, restores async storage capacity accounting, and enforces physical disk flushes for durable async file writes and appends. 7.3.0: implements IAsyncMessageStore so the SharpCoreDB provider participates in ServiceMq's async API. No API or store-format changes. 7.2.0: updates SharpCoreDB to 2.0.0.3 and resolves all SonarCloud high-severity findings in the provider (constructor cognitive complexity, row-value conversion, manifest property shadowing, and empty-catch documentation) with no API or store-format changes. 7.1.1 upgrades the provider from SharpCoreDB 1.9.3 to the 2.0.0.2 performance-first engine. SharpCoreDB documents large engine-level throughput gains in this release: debug file logging was removed from all hot paths, new primary-key tables default to the fixed-width columnar record layout, commit/overwrite writes are batched per storage page, deletes are recorded with durable commit-time markers instead of full-file rewrites, and reopen data-integrity was hardened (see SharpCoreDB docs/2.0.0.2_WHAT_CHANGED.md). New store directories default to the fastest storage mode measured for this provider's single-row workload — the legacy variable-length record layout (AutoFixedWidthRecords = false) — recorded in the store manifest and overridable per store through the DatabaseConfig constructor parameter; the engine's fixed-width columnar default, the page-based engine, and the DatabaseConfig presets remain selectable. The upgrade is fully backwards compatible: the public ITable/IDatabase API and every ServiceMq.SharpCoreDb constructor are unchanged, the on-disk store format (manifest format v1, AES-256-GCM payload envelopes) is unchanged, and stores created by the 7.1.0 / SharpCoreDB 1.9.3 release open and run unmodified under 7.1.1. net10.0 only. A master password is required and has no default. Payloads are sealed with AES-256-GCM under a PBKDF2-HMAC-SHA256 key derived from the password and a per-store salt recorded in servicemq-store.json (store format v1); the row key is authenticated as associated data. The store directory is owned exclusively by one instance via servicemq.lock. GetKeys returns ordinal order; Move flushes the destination before removing the source.