Roomzin.Sdk
2.0.0
dotnet add package Roomzin.Sdk --version 2.0.0
NuGet\Install-Package Roomzin.Sdk -Version 2.0.0
<PackageReference Include="Roomzin.Sdk" Version="2.0.0" />
<PackageVersion Include="Roomzin.Sdk" Version="2.0.0" />
<PackageReference Include="Roomzin.Sdk" />
paket add Roomzin.Sdk --version 2.0.0
#r "nuget: Roomzin.Sdk, 2.0.0"
#:package Roomzin.Sdk@2.0.0
#addin nuget:?package=Roomzin.Sdk&version=2.0.0
#tool nuget:?package=Roomzin.Sdk&version=2.0.0
Roomzin C# SDK
Official C# SDK for Roomzin — a high-performance in-memory inventory engine for booking platforms.
The SDK provides a modern, idiomatic C# interface for communicating with Roomzin servers in both standalone and clustered deployments. It automatically handles connection management, request/response demuxing, and self-healing reconnections.
Features
- Unified client for standalone and router (cluster) modes
- Built-in connection self-healing
- Automatic request routing (writes to leader, reads to followers) via router
- Fully typed C# API
- Async/await support
IAsyncDisposableclient for resource management- Type-safe API with segment support
Requirements
- .NET 6 or later
- Roomzin Server v1.x
- Roomzin Router (for cluster mode)
Installation
dotnet add package Roomzin.Sdk
Or via the NuGet Package Manager:
Install-Package Roomzin.Sdk
Client Setup
Standalone Mode
Connect directly to a standalone Roomzin server:
using Roomzin.Sdk;
var config = ConfigFactory.CreateConfig()
.WithAddr("127.0.0.1")
.WithPort(7777)
.WithMode(Mode.Standalone)
.WithTimeout(TimeSpan.FromSeconds(5))
.WithKeepAlive(TimeSpan.FromSeconds(30))
.Build();
var client = new Client(config);
await client.ConnectAsync();
await client.CloseAsync();
Cluster Mode (via Router)
Connect to a Roomzin cluster through the router:
using Roomzin.Sdk;
var config = ConfigFactory.CreateConfig()
.WithAddr("router.example.com")
.WithPort(9200)
.WithMode(Mode.Router)
.WithTimeout(TimeSpan.FromSeconds(30))
.WithKeepAlive(TimeSpan.FromSeconds(30))
.Build();
var client = new Client(config);
await client.ConnectAsync();
await client.CloseAsync();
Using Statement
using var client = new Client(config);
await client.ConnectAsync();
// Use client...
// Automatically disposed
Configuration Options
| Option | Description | Default |
|---|---|---|
WithAddr() |
Server or router address | Required |
WithPort() |
TCP port | Required |
WithMode() |
Mode.Standalone or Mode.Router |
Mode.Standalone |
WithTimeout() |
Request timeout | 2s |
WithKeepAlive() |
TCP keep-alive interval | 30s |
Segment Routing
In cluster mode, every request must specify a segment. The router uses this to route the request to the correct shard.
string segment = "us-east";
// All API methods accept segment as a parameter
await client.SetPropAsync(segment, payload);
In standalone mode, the segment parameter is ignored but still required for API compatibility. This allows you to switch between standalone and cluster modes without changing your business logic.
Property Management
SetPropAsync
Adds or updates a property.
await client.SetPropAsync("downtown", new SetPropPayload
{
Segment = "downtown",
Area = "manhattan",
PropertyId = "hotel_123",
PropertyType = "hotel",
Category = "luxury",
Stars = 4,
Latitude = 40.7128,
Longitude = -74.0060,
Amenities = new List<string> { "wifi", "pool", "gym" }
});
SearchPropAsync
Searches properties by segment, area, type, or location.
// By segment
var ids = await client.SearchPropAsync("downtown", new SearchPropPayload
{
Segment = "downtown"
});
// By area
var ids = await client.SearchPropAsync("downtown", new SearchPropPayload
{
Segment = "downtown",
Area = "manhattan"
});
// By location (radius search)
var ids = await client.SearchPropAsync("downtown", new SearchPropPayload
{
Segment = "downtown",
Latitude = 40.7128,
Longitude = -74.0060
});
PropExistAsync
Checks if a property exists.
bool exists = await client.PropExistAsync("downtown", "hotel_123");
PropRoomExistAsync
Checks if a specific room type exists for a property.
bool exists = await client.PropRoomExistAsync("downtown", new PropRoomExistPayload
{
PropertyId = "hotel_123",
RoomType = "suite"
});
PropRoomListAsync
Lists all room types for a property.
var rooms = await client.PropRoomListAsync("downtown", "hotel_123");
PropRoomDateListAsync
Lists dates with availability data for a property and room type.
var dates = await client.PropRoomDateListAsync("downtown", new PropRoomDateListPayload
{
PropertyId = "hotel_123",
RoomType = "suite"
});
Room Package Management
SetRoomPkgAsync
Sets availability, price, and rate features for a room type on a date.
await client.SetRoomPkgAsync("downtown", new SetRoomPkgPayload
{
PropertyId = "hotel_123",
RoomType = "suite",
Date = "2026-07-20",
Availability = 10,
FinalPrice = 199,
RateFeature = new List<string> { "free_cancellation", "breakfast_included" }
});
SetRoomAvlAsync
Sets exact availability for a room type on a specific date.
byte newAvail = await client.SetRoomAvlAsync("downtown", new UpdRoomAvlPayload
{
PropertyId = "hotel_123",
RoomType = "suite",
Date = "2026-07-20",
Amount = 20
});
IncRoomAvlAsync
Increases availability (e.g., on cancellation).
byte newAvail = await client.IncRoomAvlAsync("downtown", new UpdRoomAvlPayload
{
PropertyId = "hotel_123",
RoomType = "suite",
Date = "2026-07-20",
Amount = 1
});
DecRoomAvlAsync
Decreases availability (e.g., on booking).
byte newAvail = await client.DecRoomAvlAsync("downtown", new UpdRoomAvlPayload
{
PropertyId = "hotel_123",
RoomType = "suite",
Date = "2026-07-20",
Amount = 2
});
GetPropRoomDayAsync
Gets availability and pricing for a specific room on a specific date.
var day = await client.GetPropRoomDayAsync("downtown", new GetRoomDayRequest
{
PropertyId = "hotel_123",
RoomType = "suite",
Date = "2026-07-20"
});
Console.WriteLine($"Avail: {day.Availability}, Price: {day.FinalPrice}");
Search & Query
SearchAvailAsync
Searches available rooms by filters.
var results = await client.SearchAvailAsync("downtown", new SearchAvailPayload
{
Segment = "downtown",
RoomType = "suite",
Date = new List<string> { "2026-07-20", "2026-07-21" },
Limit = 50,
MinPrice = 100,
MaxPrice = 300,
Amenities = new List<string> { "wifi", "pool" },
RateFeature = new List<string> { "free_cancellation" }
});
foreach (var result in results)
{
Console.WriteLine($"Property: {result.PropertyId}");
foreach (var day in result.Days)
{
Console.WriteLine($" {day.Date}: Avail {day.Availability}, Price {day.FinalPrice}");
}
}
GetCodecsAsync
Gets the current codec registry (used internally for validation).
var codecs = await client.GetCodecsAsync();
Console.WriteLine(string.Join(", ", codecs.RateFeatures));
Delete Operations
DelRoomDayAsync
Deletes availability for a specific room on a specific date.
await client.DelRoomDayAsync("downtown", new DelRoomDayRequest
{
PropertyId = "hotel_123",
RoomType = "suite",
Date = "2026-07-20"
});
DelPropDayAsync
Deletes all data for a property on a specific date.
await client.DelPropDayAsync("downtown", new DelPropDayRequest
{
PropertyId = "hotel_123",
Date = "2026-07-20"
});
DelPropRoomAsync
Deletes a room type from a property.
await client.DelPropRoomAsync("downtown", new DelPropRoomPayload
{
PropertyId = "hotel_123",
RoomType = "suite"
});
DelPropAsync
Deletes an entire property.
await client.DelPropAsync("downtown", "hotel_123");
DelSegmentAsync
Deletes a segment and all properties within it.
await client.DelSegmentAsync("downtown");
Error Handling
All async methods throw RoomzinException. Use the static helper methods to classify errors:
try
{
await client.SetRoomPkgAsync("downtown", payload);
}
catch (RoomzinException ex) when (RoomzinException.IsRequest(ex))
{
// Business rule violation - fix the request
Console.WriteLine($"Request error: {ex.Code}");
}
catch (RoomzinException ex) when (RoomzinException.IsRetry(ex))
{
// Temporary condition - retry with backoff
await Task.Delay(100);
await client.SetRoomPkgAsync("downtown", payload);
}
catch (RoomzinException ex) when (RoomzinException.IsClient(ex))
{
// Authentication or protocol errors
Console.WriteLine($"Client error: {ex.Message}");
}
catch (RoomzinException ex) when (RoomzinException.IsInternal(ex))
{
// Unexpected server response
throw new InvalidOperationException("Internal error", ex);
}
Error Categories
| Category | Description | Action |
|---|---|---|
| Client | Authentication or protocol errors | Check credentials and configuration |
| Request | Invalid input or business rule violation | Fix request, don't retry |
| Retry | Temporary server condition (429, 503) | Retry with backoff |
| Internal | Unexpected server response | Log and investigate |
Client Lifecycle
Create a single client during application startup and reuse it throughout your application.
// ✅ Good - create once, reuse
var client = new Client(config);
await client.ConnectAsync();
// Use client everywhere...
await client.CloseAsync();
// ❌ Bad - creating per request
foreach (var req in requests)
{
var client = new Client(config); // Don't do this
await client.SetRoomPkgAsync("downtown", req);
await client.CloseAsync();
}
The client is safe for concurrent use and manages TCP connections internally.
Architecture
Standalone Mode
[SDK] → [Standalone Server]
- Single TCP connection
- Direct communication
- Self-healing on disconnection
Cluster Mode
[SDK] → [Router] → [Shard Leader/Followers]
- SDK sends segment and isWrite flag in header
- Router routes writes to leader, reads to followers
- Router handles cluster topology
- SDK maintains single connection to router
Protocol
The SDK uses a framed binary protocol:
Standalone Frame:
[0xFF][ClrID(4)][TotalLen(4)][Payload]
Router Frame:
[0xFE][TotalLen(4)][SegmentLen(1)][Segment(n)][IsWrite(1)][ShardFrame]
Where ShardFrame is the standalone frame format.
Examples
A complete smoke example is available in the examples/csharp/ directory. It demonstrates the SDK's core features and can be run as a reference implementation or to verify your Roomzin setup.
cd examples/csharp
dotnet run
Documentation
For Roomzin concepts, deployment, and administration:
https://m-javani.github.io/roomzin-doc/docs.html
Contributing
Contributions are welcome! Please open an issue before proposing large changes.
All contributions are subject to the BUSL-1.1 License terms.
License
This SDK is licensed under the BUSL-1.1 License.
Note: This SDK communicates with Roomzin Server, which requires a valid Roomzin license.
Support
- Documentation: roomzin-doc
- Community Q&A: GitHub Discussions
- Issues: GitHub Issues
- Security: mehdy.javany@gmail.com
Related Repositories
- Roomzin Quickstart — Local Docker cluster
- Roomzin Bench — Benchmarking tool
| 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 was computed. 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
- System.Buffers (>= 4.5.1)
- System.Threading.Channels (>= 7.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.