-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Ability to run the local-drone-control-scala as multi node (#1005)
- Loading branch information
1 parent
6cd9e47
commit 975f41c
Showing
12 changed files
with
398 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
samples/grpc/local-drone-control-scala/ddl-scripts/create_tables.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
-- Only needed if running multi-node clustered version of the app with a separate standalone PostgreSQL server | ||
|
||
CREATE TABLE IF NOT EXISTS event_journal( | ||
slice INT NOT NULL, | ||
entity_type VARCHAR(255) NOT NULL, | ||
persistence_id VARCHAR(255) NOT NULL, | ||
seq_nr BIGINT NOT NULL, | ||
db_timestamp timestamp with time zone NOT NULL, | ||
|
||
event_ser_id INTEGER NOT NULL, | ||
event_ser_manifest VARCHAR(255) NOT NULL, | ||
event_payload BYTEA NOT NULL, | ||
|
||
deleted BOOLEAN DEFAULT FALSE NOT NULL, | ||
writer VARCHAR(255) NOT NULL, | ||
adapter_manifest VARCHAR(255), | ||
tags TEXT ARRAY, | ||
|
||
meta_ser_id INTEGER, | ||
meta_ser_manifest VARCHAR(255), | ||
meta_payload BYTEA, | ||
|
||
PRIMARY KEY(persistence_id, seq_nr) | ||
); | ||
|
||
-- `event_journal_slice_idx` is only needed if the slice based queries are used | ||
CREATE INDEX IF NOT EXISTS event_journal_slice_idx ON event_journal(slice, entity_type, db_timestamp, seq_nr); | ||
|
||
CREATE TABLE IF NOT EXISTS snapshot( | ||
slice INT NOT NULL, | ||
entity_type VARCHAR(255) NOT NULL, | ||
persistence_id VARCHAR(255) NOT NULL, | ||
seq_nr BIGINT NOT NULL, | ||
db_timestamp timestamp with time zone, | ||
write_timestamp BIGINT NOT NULL, | ||
ser_id INTEGER NOT NULL, | ||
ser_manifest VARCHAR(255) NOT NULL, | ||
snapshot BYTEA NOT NULL, | ||
tags TEXT ARRAY, | ||
meta_ser_id INTEGER, | ||
meta_ser_manifest VARCHAR(255), | ||
meta_payload BYTEA, | ||
|
||
PRIMARY KEY(persistence_id) | ||
); | ||
|
||
-- `snapshot_slice_idx` is only needed if the slice based queries are used together with snapshot as starting point | ||
CREATE INDEX IF NOT EXISTS snapshot_slice_idx ON snapshot(slice, entity_type, db_timestamp); | ||
|
||
CREATE TABLE IF NOT EXISTS durable_state ( | ||
slice INT NOT NULL, | ||
entity_type VARCHAR(255) NOT NULL, | ||
persistence_id VARCHAR(255) NOT NULL, | ||
revision BIGINT NOT NULL, | ||
db_timestamp timestamp with time zone NOT NULL, | ||
|
||
state_ser_id INTEGER NOT NULL, | ||
state_ser_manifest VARCHAR(255), | ||
state_payload BYTEA NOT NULL, | ||
tags TEXT ARRAY, | ||
|
||
PRIMARY KEY(persistence_id, revision) | ||
); | ||
|
||
-- `durable_state_slice_idx` is only needed if the slice based queries are used | ||
CREATE INDEX IF NOT EXISTS durable_state_slice_idx ON durable_state(slice, entity_type, db_timestamp, revision); | ||
|
||
-- Primitive offset types are stored in this table. | ||
-- If only timestamp based offsets are used this table is optional. | ||
-- Configure akka.projection.r2dbc.offset-store.offset-table="" if the table is not created. | ||
CREATE TABLE IF NOT EXISTS akka_projection_offset_store ( | ||
projection_name VARCHAR(255) NOT NULL, | ||
projection_key VARCHAR(255) NOT NULL, | ||
current_offset VARCHAR(255) NOT NULL, | ||
manifest VARCHAR(32) NOT NULL, | ||
mergeable BOOLEAN NOT NULL, | ||
last_updated BIGINT NOT NULL, | ||
PRIMARY KEY(projection_name, projection_key) | ||
); | ||
|
||
-- Timestamp based offsets are stored in this table. | ||
CREATE TABLE IF NOT EXISTS akka_projection_timestamp_offset_store ( | ||
projection_name VARCHAR(255) NOT NULL, | ||
projection_key VARCHAR(255) NOT NULL, | ||
slice INT NOT NULL, | ||
persistence_id VARCHAR(255) NOT NULL, | ||
seq_nr BIGINT NOT NULL, | ||
-- timestamp_offset is the db_timestamp of the original event | ||
timestamp_offset timestamp with time zone NOT NULL, | ||
-- timestamp_consumed is when the offset was stored | ||
-- the consumer lag is timestamp_consumed - timestamp_offset | ||
timestamp_consumed timestamp with time zone NOT NULL, | ||
PRIMARY KEY(slice, projection_name, timestamp_offset, persistence_id, seq_nr) | ||
); | ||
|
||
CREATE TABLE IF NOT EXISTS akka_projection_management ( | ||
projection_name VARCHAR(255) NOT NULL, | ||
projection_key VARCHAR(255) NOT NULL, | ||
paused BOOLEAN NOT NULL, | ||
last_updated BIGINT NOT NULL, | ||
PRIMARY KEY(projection_name, projection_key) | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Only needed if running multi-node clustered version of the app with a separate standalone PostgreSQL server locally | ||
version: '2.2' | ||
services: | ||
postgres-db: | ||
image: postgres:latest | ||
container_name: local_drone_control_db | ||
ports: | ||
- 5433:5432 | ||
environment: | ||
POSTGRES_USER: postgres | ||
POSTGRES_PASSWORD: postgres | ||
healthcheck: | ||
test: ['CMD', 'pg_isready', "-q", "-d", "postgres", "-U", "postgres"] | ||
interval: 5s | ||
retries: 5 | ||
start_period: 5s | ||
timeout: 5s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
samples/grpc/local-drone-control-scala/src/main/resources/local-persistence.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Used for running the local-drone-control as a cluster with several nodes | ||
# through the local.drones.ClusteredMain and a separate PostgreSQL database | ||
|
||
akka.persistence.r2dbc.connection-factory = ${akka.persistence.r2dbc.postgres} | ||
akka { | ||
persistence { | ||
journal { | ||
plugin = "akka.persistence.r2dbc.journal" | ||
} | ||
snapshot-store { | ||
plugin = "akka.persistence.r2dbc.snapshot" | ||
} | ||
state { | ||
plugin = "akka.persistence.r2dbc.state" | ||
} | ||
|
||
r2dbc { | ||
connection-factory { | ||
host = "localhost" | ||
host = ${?DB_HOST} | ||
# note: different port for running in parallel with db for restaurant-drone-deliveries-service | ||
port = 5433 | ||
database = "postgres" | ||
user = "postgres" | ||
user = ${?DB_USER} | ||
password = "postgres" | ||
password = ${?DB_PASSWORD} | ||
} | ||
} | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
samples/grpc/local-drone-control-scala/src/main/resources/local-shared.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Used for running the local-drone-control as a cluster with several nodes | ||
# through the local.drones.ClusteredMain and a separate PostgreSQL database | ||
include "cluster" | ||
include "grpc" | ||
include "local-persistence.conf" | ||
|
||
local-drone-control.grpc.interface = "127.0.0.1" | ||
akka.remote.artery.canonical.hostname = "127.0.0.1" | ||
akka.management.http.hostname = "127.0.0.1" | ||
|
||
local-drone-control { | ||
nr-of-event-producers = 4 | ||
# unique identifier for the instance of local control, must be known up front by the cloud service | ||
location-id = "sweden/stockholm/kungsholmen" | ||
location-id = ${?LOCATION_ID} | ||
|
||
ask-timeout = 3s | ||
} | ||
|
||
akka.management { | ||
http { | ||
port = 9201 | ||
port = ${?HTTP_MGMT_PORT} | ||
} | ||
cluster.bootstrap { | ||
contact-point-discovery { | ||
service-name = "local-drone-control" | ||
discovery-method = kubernetes-api | ||
required-contact-point-nr = 1 | ||
required-contact-point-nr = ${?REQUIRED_CONTACT_POINT_NR} | ||
} | ||
} | ||
} | ||
|
||
akka.management.cluster.bootstrap.contact-point-discovery { | ||
service-name = "local-drone-control" | ||
discovery-method = config | ||
# boostrap filters ports with the same IP assuming they are previous instances running on the same node | ||
# unless a port is specified | ||
port-name = "management" | ||
required-contact-point-nr = 1 | ||
# config service discovery never changes | ||
stable-margin = 1 ms | ||
# bootstrap without all the nodes being up | ||
contact-with-all-contact-points = false | ||
} | ||
|
||
akka.discovery.config.services { | ||
"local-drone-control" { | ||
endpoints = [ | ||
{host = "127.0.0.1", port = 9201} | ||
{host = "127.0.0.1", port = 9202} | ||
{host = "127.0.0.1", port = 9203} | ||
] | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
samples/grpc/local-drone-control-scala/src/main/resources/local1.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Used for running the local-drone-control as a cluster with several nodes | ||
# through the local.drones.ClusteredMain and a separate PostgreSQL database | ||
include "local-shared" | ||
|
||
|
||
local-drone-control.grpc.port = 8080 | ||
|
||
akka.remote.artery.canonical.port = 2651 | ||
akka.management.http.port = 9201 | ||
|
9 changes: 9 additions & 0 deletions
9
samples/grpc/local-drone-control-scala/src/main/resources/local2.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Used for running the local-drone-control as a cluster with several nodes | ||
# through the local.drones.ClusteredMain and a separate PostgreSQL database | ||
include "local-shared" | ||
|
||
|
||
local-drone-control.grpc.port = 8081 | ||
|
||
akka.management.http.port = 9202 | ||
akka.remote.artery.canonical.port = 2652 |
9 changes: 9 additions & 0 deletions
9
samples/grpc/local-drone-control-scala/src/main/resources/local3.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Used for running the local-drone-control as a cluster with several nodes | ||
# through the local.drones.ClusteredMain and a separate PostgreSQL database | ||
include "local-shared" | ||
|
||
|
||
local-drone-control.grpc.port = 8082 | ||
|
||
akka.remote.artery.canonical.port = 2653 | ||
akka.management.http.port = 9203 |
68 changes: 68 additions & 0 deletions
68
samples/grpc/local-drone-control-scala/src/main/scala/local/drones/ClusteredMain.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package local.drones | ||
|
||
import akka.actor.typed.scaladsl.Behaviors | ||
import akka.actor.typed.{ ActorSystem, Behavior } | ||
import akka.cluster.typed.{ ClusterSingleton, SingletonActor } | ||
import akka.management.cluster.bootstrap.ClusterBootstrap | ||
import akka.management.scaladsl.AkkaManagement | ||
|
||
/** | ||
* Main for starting the local-drone-control as a cluster rather than a single self-contained node. Requires | ||
* a separate database, start with config from local{1,2,3}.conf files for running as cluster locally. | ||
*/ | ||
object ClusteredMain { | ||
|
||
def main(args: Array[String]): Unit = { | ||
ActorSystem[Nothing](rootBehavior(), "local-drone-control") | ||
} | ||
|
||
private def rootBehavior(): Behavior[Nothing] = Behaviors.setup[Nothing] { | ||
context => | ||
val settings = Settings(context.system) | ||
|
||
context.log | ||
.info("Local Drone Control [{}] starting up", settings.locationId) | ||
|
||
// Bootstrap cluster | ||
AkkaManagement(context.system).start() | ||
ClusterBootstrap(context.system).start() | ||
|
||
// keep track of local drones, project aggregate info to the cloud | ||
Drone.init(context.system) | ||
DroneEvents.initEventToCloudDaemonProcess(settings)(context.system) | ||
|
||
// consume delivery events from the cloud service, single queue in cluster singleton | ||
val deliveriesQueue = | ||
ClusterSingleton(context.system).init( | ||
SingletonActor[DeliveriesQueue.Command]( | ||
DeliveriesQueue(), | ||
"DeliveriesQueue")) | ||
|
||
// single queue, single grpc projection consumer | ||
ClusterSingleton(context.system).init( | ||
SingletonActor( | ||
DeliveryEvents.projectionBehavior(deliveriesQueue, settings)( | ||
context.system), | ||
"DeliveriesProjection")) | ||
val deliveriesQueueService = | ||
new DeliveriesQueueServiceImpl(settings, deliveriesQueue)( | ||
context.system) | ||
|
||
val grpcInterface = | ||
context.system.settings.config | ||
.getString("local-drone-control.grpc.interface") | ||
val grpcPort = | ||
context.system.settings.config.getInt("local-drone-control.grpc.port") | ||
val droneService = | ||
new DroneServiceImpl(deliveriesQueue, settings)(context.system) | ||
LocalDroneControlServer.start( | ||
grpcInterface, | ||
grpcPort, | ||
context.system, | ||
droneService, | ||
deliveriesQueueService) | ||
|
||
Behaviors.empty | ||
} | ||
|
||
} |
Oops, something went wrong.