|
@@ -388,7 +388,7 @@ void DatabaseService::start() {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- spdlog::info("Starting database service on {}:{}", config_.bindAddress, config_.rpcPort);
|
|
|
|
|
|
|
+ spdlog::info("Starting database service with {} listener(s)", config_.listeners.size());
|
|
|
|
|
|
|
|
// Start components
|
|
// Start components
|
|
|
store_->start();
|
|
store_->start();
|
|
@@ -1103,25 +1103,13 @@ void DatabaseService::applyReplicatedEntry(const databasepb::ReplicationEntry& e
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DatabaseService::startGrpcServer() {
|
|
void DatabaseService::startGrpcServer() {
|
|
|
- std::string serverAddress = config_.bindAddress + ":" + std::to_string(config_.rpcPort);
|
|
|
|
|
-
|
|
|
|
|
- grpc::ServerBuilder builder;
|
|
|
|
|
- builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
|
|
|
|
|
- builder.RegisterService(storageImpl_.get());
|
|
|
|
|
- builder.RegisterService(replicationImpl_.get());
|
|
|
|
|
|
|
+ if (config_.listeners.empty()) {
|
|
|
|
|
+ // Should never hit — parseConfig's back-compat shim always
|
|
|
|
|
+ // synthesises at least one. Defend anyway.
|
|
|
|
|
+ throw std::runtime_error("startGrpcServer: no listeners configured");
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // Configurable message sizes (default 100 MB for file uploads)
|
|
|
|
|
const int64_t mb = 1024 * 1024;
|
|
const int64_t mb = 1024 * 1024;
|
|
|
- builder.SetMaxReceiveMessageSize(
|
|
|
|
|
- static_cast<int>(config_.grpc.maxReceiveMessageSizeMb * mb));
|
|
|
|
|
- builder.SetMaxSendMessageSize(
|
|
|
|
|
- static_cast<int>(config_.grpc.maxSendMessageSizeMb * mb));
|
|
|
|
|
-
|
|
|
|
|
- // ResourceQuota bounds total inbound buffer memory across all RPCs
|
|
|
|
|
- grpc::ResourceQuota quota("smartbotic-db");
|
|
|
|
|
- quota.Resize(config_.grpc.resourceQuotaMemoryMb * mb);
|
|
|
|
|
- builder.SetResourceQuota(quota);
|
|
|
|
|
-
|
|
|
|
|
spdlog::info("gRPC config: recv={}MB send={}MB quota={}MB subs={} files={}",
|
|
spdlog::info("gRPC config: recv={}MB send={}MB quota={}MB subs={} files={}",
|
|
|
config_.grpc.maxReceiveMessageSizeMb,
|
|
config_.grpc.maxReceiveMessageSizeMb,
|
|
|
config_.grpc.maxSendMessageSizeMb,
|
|
config_.grpc.maxSendMessageSizeMb,
|
|
@@ -1129,20 +1117,55 @@ void DatabaseService::startGrpcServer() {
|
|
|
config_.grpc.maxConcurrentSubscribeStreams,
|
|
config_.grpc.maxConcurrentSubscribeStreams,
|
|
|
config_.grpc.maxConcurrentFileStreams);
|
|
config_.grpc.maxConcurrentFileStreams);
|
|
|
|
|
|
|
|
- grpcServer_ = builder.BuildAndStart();
|
|
|
|
|
|
|
+ grpcServers_.reserve(config_.listeners.size());
|
|
|
|
|
|
|
|
- if (!grpcServer_) {
|
|
|
|
|
- throw std::runtime_error("Failed to start gRPC server on " + serverAddress);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (const auto& listener : config_.listeners) {
|
|
|
|
|
+ const std::string addr = listener.bind + ":" + std::to_string(listener.port);
|
|
|
|
|
+
|
|
|
|
|
+ grpc::ServerBuilder builder;
|
|
|
|
|
+
|
|
|
|
|
+ // v2.4 Stage B — InsecureServerCredentials for every listener
|
|
|
|
|
+ // regardless of `tls.enabled`. Stage C swaps in SslServerCredentials
|
|
|
|
|
+ // when the listener is configured for TLS; Stage D adds the
|
|
|
|
|
+ // per-listener auth interceptor.
|
|
|
|
|
+ std::shared_ptr<grpc::ServerCredentials> creds =
|
|
|
|
|
+ grpc::InsecureServerCredentials();
|
|
|
|
|
+ builder.AddListeningPort(addr, creds);
|
|
|
|
|
|
|
|
- spdlog::info("gRPC server listening on {}", serverAddress);
|
|
|
|
|
|
|
+ builder.RegisterService(storageImpl_.get());
|
|
|
|
|
+ builder.RegisterService(replicationImpl_.get());
|
|
|
|
|
+
|
|
|
|
|
+ builder.SetMaxReceiveMessageSize(
|
|
|
|
|
+ static_cast<int>(config_.grpc.maxReceiveMessageSizeMb * mb));
|
|
|
|
|
+ builder.SetMaxSendMessageSize(
|
|
|
|
|
+ static_cast<int>(config_.grpc.maxSendMessageSizeMb * mb));
|
|
|
|
|
+
|
|
|
|
|
+ grpc::ResourceQuota quota("smartbotic-db-" + addr);
|
|
|
|
|
+ quota.Resize(config_.grpc.resourceQuotaMemoryMb * mb);
|
|
|
|
|
+ builder.SetResourceQuota(quota);
|
|
|
|
|
+
|
|
|
|
|
+ auto server = builder.BuildAndStart();
|
|
|
|
|
+ if (!server) {
|
|
|
|
|
+ throw std::runtime_error("Failed to start gRPC server on " + addr);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // v2.4 Stage B log line — listener identity printed so operators
|
|
|
|
|
+ // know exactly which interface is exposed with which policy.
|
|
|
|
|
+ // Stage C/D will extend with TLS + auth status.
|
|
|
|
|
+ spdlog::info("gRPC listener up: {} (tls={}, auth_required={})",
|
|
|
|
|
+ addr,
|
|
|
|
|
+ listener.tls.enabled ? "true" : "false",
|
|
|
|
|
+ listener.auth.required ? "true" : "false");
|
|
|
|
|
+
|
|
|
|
|
+ grpcServers_.push_back(std::move(server));
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DatabaseService::stopGrpcServer() {
|
|
void DatabaseService::stopGrpcServer() {
|
|
|
- if (grpcServer_) {
|
|
|
|
|
- grpcServer_->Shutdown();
|
|
|
|
|
- grpcServer_.reset();
|
|
|
|
|
|
|
+ for (auto& server : grpcServers_) {
|
|
|
|
|
+ if (server) server->Shutdown();
|
|
|
}
|
|
}
|
|
|
|
|
+ grpcServers_.clear();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // namespace smartbotic::database
|
|
} // namespace smartbotic::database
|