package server
- User Manual
- Developer Manual
- If your goal is to extend a service with business specific components then see glngn.server.ServiceFragment.
- If your goal is to customize the configuration or prelude to better suite a business domain then see glngn.server.host.HostApp.
- If you are debugging a failure of a glngn server process and have the exit code then see glngn.server.host.ExitCodes$
- Grouped
- Alphabetic
- By Inheritance
- server
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
- type AppEnvironment = Blocking with Clock with Logging with Random with System with ServerConfig with InjectorProvider
- type AppIO[+E, +A] = ZIO[AppEnvironment, E, A]
- type AppRuntime = Runtime[AppEnvironment]
- type AppTask[+A] = ZIO[AppEnvironment, Throwable, A]
- type AppUIO[+A] = ZIO[AppEnvironment, Nothing, A]
-
sealed abstract
class
Config extends FixedConfigProps with DerivedConfigFromFixedProps
See Config$ for methods to load configs.
See Config$ for methods to load configs. The
print-config
andprint-full-config
of glngn.server.host.HostApp can be used to examine the config.Configuration loading is a bit convoluted. The primary aspect driving this is: The initial values of configurations that must be loaded from the hocon must also be derived using functions on the configuration and environment. Which necessitates first loading a partial config then loading the full config with derived values injected.
The design used here loads the config through the follow steps:
1. First the configuration file is loaded with all derived values equal to exactly "<derived TYPE>". Where TYPE is a description. This is a
FixedConfigProps
instantiated byConfig.base
.Only configuration in
glngn.server
will be derived. All other configuration will reference the value fromglngn.server
2. Initial tuning factors are instantiated from (base, environment probes) 3. All properties with "<derived TYPE>" are derived given (base, tuning) 4. All derived properties are *serialized* to corresponding hocon. 5. This serialized typesafe config is applied *prior to application.conf*. This forms the Config. Which finally provides the full Config interface of FixedConfigProps, DerivedConfigProps, and an
initialTuning
of TuningConfigProps.The result is a config that should be easy enough to understand from reading
reference.conf
. With the exact config ofglngn.server
output by theconfig
server execution option. -
trait
ServiceEntity extends ServiceActor
An event sourced persistent entity definition.
An event sourced persistent entity definition. The entity refers to all actors defined by the the Id.
This is implemented using typed akka persistent actors and cluster sharding. Additional functionality:
- always replies when handing a request - will automatically derive a
JSON
codec forStorage
events - StopEnvelope will always stop the entity - entity will automatically passivate after no eventsimport glngn.server.prelude._ final object MyServiceEntity extends ServiceEntity { val name = "my-service-entity" // example declaration of state as case class final case class State(state: String) extends Message // standard Proto and Storage declarations as sealed traits sealed trait Proto extends Message sealed trait Storage extends Proto // a request event that's recorded to storage final case class Add(value: String) extends Command[State] with Storage with Proto def activity(injector: ImpureInjector, id: Id) = new Activity(injector) { val init = State(Map.empty) def protoHandler(ctx: ActorContext[Envelope], state: State) = { case persistedEvent: Storage => Handler.persist(persistedEvent) case _: Proto => Handler.none } def storageHandler(state: State) = { case add: Add => state.copy(state = state.state + add.value) } } }
-
abstract
class
ServiceFragment extends ActorService with ServiceEndpoints
A service fragment is an object defining a logical service.
A service fragment is an object defining a logical service. Service fragments must be instantiated under a group with a name to use. This scopes all endpoints, authorization, and entity data to that group and name.
An object extending this class declares a new service fragment. A service has a protocol of commands, queries and events. Operators can use the protocol directly. Users can only use the protocol through the declared endpoints.
The usability focus is on rapid development and data acquisition:
- easy declaration of the commands, queries and events
- automatic auditing
- components for common business as a service activities
A service is three declarations:
- A protocol consisting of commands and queries
- A mapping from protocol messages to implementations
- an interface exported to users as endpoints
This is implemented in this EDSL as:
- Types in the Proto hierarchy. Commands extend Command and Queries extend Query.
- Implementations defined by (partial) functions from messages in this protocol to a handler. Handlers can delegate to akka actors, event source entities, ZIO actions, or plain functions.
- the exports of commands and queries are REST endpoints. These consist of explicit (verb, path components, data) and implicit (auth token, session token, csrf token, origin) data plus a mapping to the Proto.
Scopes If services.IntegerCounters was instantiated under a group
doors
with the service nameentrances
andexits
then these would not share data. The entity/doors/entrances/front
would have a different state than/doors/exits/front
. Even though the object,IntegerCounters
, is the same. , Minimal service fragment definition
import glngn.prelude._ object MinimalServiceFragment extends ServiceFragment { sealed trait Proto extends Message }
, A hypothetical service fragment definition
// a hypothetical service for account balances final object ClientBalanceFragment extends ServiceFragment { type AccountId = EntityId type CurrencyValue = Int // fractions of currency unit // messages in the protocol sealed trait Proto extends Message // a command to increase the balance of an account case class IncBalanceForAccount(account: AccountId, amount: CurrencyValue) extends Command[CurrencyValue] with Proto // a command to decrease the balance of an account case class DecBalanceForAccount(account: AccountId, amount: CurrencyValue) extends Command[CurrencyValue] with Proto // a query to retrieve the account balance case class GetBalanceForAccount(account: AccountId) extends Query[CurrencyValue] with Proto // an event outside of the command/query model. case class RequestAudit(account: AccountId) extends Proto override def instantiate(env: InstanceEnv) = new Instance(env) { import Bindings.{delegate, entity, async} // the service protocol is implemented using... val bindings = bindingsChain( // ... a akka typed Behavior[Envelope] delegate delegate { Behaviors.receiveMessagePartial case Event(RequestAudit) => ??? } // Note the use of a partial function: unhandled messages will propagate to the // next binding. (Even if the delegate behavior above changes) }, // ... operations on a named counter entity entity(NamedValue) { case IncBalanceForAccount(accountId, amount) => CounterEntity.Inc(amount) -> accountId case DecBalanceForAccount(accountId, amount) => CounterEntity.Dec(amount) -> accountId case GetBalanceForAccount(accountId) => CounterEntity.Get -> accountId }, // ... a daemon sending Proto messages back to this service async(OrdersOverSMSBehavior) // where OrdersOverSMSBehavior being a [[ServiceActorDaemon]] ) import Endpoints.{query, command} // The protocol is exported to users with the endpoints def endpoints: Endpoints[_] = endpointsChain( // results in the REST interface: // // GET $accountName // POST $accountName/inc // POST $accountName/dec // // once instantiated this is schema can be viewed under /openapi.json query.entityId { accountName => GetBalanceForAccount(accountName) }, command.entityId.slug("inc").value[CurrencyValue] { (accountId, amount) => IncBalanceForAccount(accountId, amount) }, command.entityId.slug("dec").value[CurrencyValue] { (accountId, amount) => DecBalanceForAccount(accountId, amount) } ) } }
Examples:
Value Members
- object AppEnvironment
-
object
AppIO
Accessors of AppEnvironment in AppRuntime for AppIO, AppUIO, AppTask
- object Config
glngn server is a low-code business process as a service rapid development system. Conceptually similar to a programmable Microsoft Access or Apple FileMaker for scalable event sourced business services. In addition to a library, a standalone application is provided that is useful with minimal ceremony. This can be customized with a simple API. As well as deployed to a kubernetes cluster should those advantages be required.
A deployment is cluster of glngn.server.node.AppNodes serving a dynamic composition of glngn.server.ServiceFragments. Deployments are designed to be fully usable as a standalone local application or a kubernetes service.
Contact support@dogheadbone.com for support and licensing.