Packages

  • package root

    glngn server is a low-code business process as a service rapid development system.

    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.

    Definition Classes
    root
  • package glngn
    Definition Classes
    root
  • package server

    Definition Classes
    glngn
  • package core
  • package entities
  • package host
  • package model
  • package prelude

    Provides a custom prelude that re-exports common dependencies.

    Provides a custom prelude that re-exports common dependencies. This will re-export

    Useful for initial developments. If the external prelude conflicts with additional imports there will be odd "no implicit found" errors. In which case this prelude is not appropriate to use.

    import glngn.prelude._

    Use of this prelude is not required. Each aspect is provided as a mix-in and separate object.

    For example, to import only the types and values defined in glngn.server that are generally useful for development:

    import glngn.server.prelude.GlngnServerPrelude._
  • package services
  • AppEnvironment
  • AppIO
  • Config
  • ServiceEntity
  • ServiceFragment
p

glngn

server

package server

Linear Supertypes
Ordering
  1. Grouped
  2. Alphabetic
  3. By Inheritance
Inherited
  1. server
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Type Members

  1. type AppEnvironment = Blocking with Clock with Logging with Random with System with ServerConfig with InjectorProvider
  2. type AppIO[+E, +A] = ZIO[AppEnvironment, E, A]

  3. type AppRuntime = Runtime[AppEnvironment]

  4. type AppTask[+A] = ZIO[AppEnvironment, Throwable, A]

  5. type AppUIO[+A] = ZIO[AppEnvironment, Nothing, A]

  6. 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 and print-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 by Config.base.

    Only configuration in glngn.server will be derived. All other configuration will reference the value from glngn.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 of glngn.server output by the config server execution option.

  7. 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 for Storage events - StopEnvelope will always stop the entity - entity will automatically passivate after no events

    import 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)
        }
      }
    }
  8. 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.
    Examples:
    1. Scopes If services.IntegerCounters was instantiated under a group doors with the service name entrances and exits 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.

    2. ,
    3. Minimal service fragment definition

      import glngn.prelude._
      
      object MinimalServiceFragment extends ServiceFragment {
        sealed trait Proto extends Message
      }
    4. ,
    5. 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)
            }
          )
        }
      }

Value Members

  1. object AppEnvironment
  2. object AppIO

    Accessors of AppEnvironment in AppRuntime for AppIO, AppUIO, AppTask

  3. object Config

Inherited from AnyRef

Inherited from Any

Domain

Service Logic

Implementation Detail

Ungrouped