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
    Definition Classes
    server
  • package entities
    Definition Classes
    server
  • package host
    Definition Classes
    server
  • package model
    Definition Classes
    server
  • 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._
    Definition Classes
    server
  • package services
    Definition Classes
    server
  • AppEnvironment
  • AppIO
  • Config
  • ServiceEntity
  • ServiceFragment
c

glngn.server

ServiceFragment

abstract class ServiceFragment extends ActorService with ServiceEndpoints

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)
          }
        )
      }
    }
Known Subclasses
Ordering
  1. Grouped
  2. Alphabetic
  3. By Inheritance
Inherited
  1. ServiceFragment
  2. ServiceEndpoints
  3. ActorService
  4. ServiceBindings
  5. ServiceActor
  6. DirectLogging
  7. AnyRef
  8. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Instance Constructors

  1. new ServiceFragment(logicalIdInput: String = "")

Type Members

  1. final type AnyRequest = Proto with Request[_]

    AnyRequest is a Command or Query with no particular response type.

    AnyRequest is a Command or Query with no particular response type.

    Definition Classes
    ServiceActor
  2. final type Bindings[A] = FreeApplicative[BindingsOp, A]

    Type of bindings declaration.

    Type of bindings declaration.

    Definition Classes
    ServiceBindings
  3. final type Delegate = ActorRef[Envelope]

    The delegate is an actor accepting events in Envelope messages.

    The delegate is an actor accepting events in Envelope messages.

    Definition Classes
    ServiceBindings
  4. final type Endpoints[A] = FreeApplicative[EndpointsOp, A]

    Definition Classes
    ServiceEndpoints
  5. abstract class Instance extends EndpointsInstance with ServiceInstance

  6. case class InstanceEnv(spawner: ActorSpawner, injector: ImpureInjector, groupId: GroupId, serviceId: ServiceId) extends BindingsInstanceEnv with Product with Serializable

  7. abstract type Proto <: Message

    The commands, queries and events all implement Proto.

    The commands, queries and events all implement Proto. Easy inferrence of operations schema and endpoint schema assumes the use of a sealed trait.

    Definition Classes
    ServiceActor
    Examples:
    1. a typical definition

      sealed trait Proto extends Message
    2. ,
    3. an event type AnEvent in Proto

      sealed trait Proto extends Message
      case class AnEvent(msg: String) extends Proto
  8. trait ServiceInstance extends BindingsInstance

    Definition Classes
    ActorService
  9. abstract class Command[Response] extends Request[Response] with proto.ProtoDecl.Command with proto.ProtoDecl.Request

    All commands are Requests with Proto: extends Command[R] with Proto.

    All commands are Requests with Proto: extends Command[R] with Proto.

    sealed trait Proto extends Message
    case class ExampleCommand(msg: String) extends Command[ExampleResponse] with Proto
    Definition Classes
    ServiceActor
  10. sealed trait Envelope extends Product with Message with Serializable

    A Proto event with additional attributes and claims.

    A Proto event with additional attributes and claims. To pattern match on an Envelope use the Event.unapply or Request.unapply extractors.

    val behavior: Behavior[Envelope] = Behaviors.receiveMessagePartial {
      case Event(SomeEvent(eventData)) => ???
      case Request(scope, SomeCommand(eventData)) => ???
    }

    An Envelope can be implicitly constructed from any Proto.

    val delegate: ActorRef[Envelope] = ???
    val anEvent: Proto = SomeEvent(eventData)
    delegate ! anEvent
    Definition Classes
    ServiceActor
  11. abstract class Query[Response] extends Request[Response] with proto.ProtoDecl.Query with proto.ProtoDecl.Request

    All queries are Requests with Proto: extends Query[R] with Proto.

    All queries are Requests with Proto: extends Query[R] with Proto.

    sealed trait Proto extends Message
    case class ExampleQuery(msg: String) extends Query[ExampleResponse] with Proto
    Definition Classes
    ServiceActor
  12. sealed abstract class Request[R] extends AnyRef

    A protocol event can be declared as a Request using Command or Query.

    A protocol event can be declared as a Request using Command or Query. The type parameter is the response that resolves the request.

    sealed trait Proto extends Message
    case class ExampleCommand(msg: String) extends Command[ExampleResponse] with Proto
    case class ExampleQuery(msg: String) extends Query[ExampleResponse] with Proto
    Definition Classes
    ServiceActor
  13. trait BindingsInstance extends AnyRef

    Definition Classes
    ServiceBindings
  14. implicit class DelegateOps extends AnyRef

    Definition Classes
    ServiceBindings
  15. abstract class EndpointsInstance extends BindingsInstance

    Definition Classes
    ServiceEndpoints
  16. sealed trait EndpointsOp[A] extends AnyRef

    Definition Classes
    ServiceEndpoints

Abstract Value Members

  1. abstract def instantiate(env: InstanceEnv): Instance

    Instantiates this service fragment with the given environment.

    Instantiates this service fragment with the given environment.

    TODO: composition instead of requiring the Instance interface?

    Examples:
    1. An empty instance with no bindings or endpoints.

      def instantiate(env: InstanceEnv) = Instance.empty(env)
    2. ,
    3. The empty instance is exactly

      def instantiate(env: InstanceEnv) = new Instance(env) {
        val bindings: Bindings[_] = Bindings.empty
        def endpoints: Endpoints[_] = Endpoints.empty
      }

Concrete Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  5. def clone(): AnyRef
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... ) @native()
  6. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  7. def equals(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  8. def finalize(): Unit
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  9. final def getClass(): Class[_]
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  10. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  11. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  12. lazy val logger: prelude.external.Logger

    Attributes
    protected
    Definition Classes
    DirectLogging
  13. val logicalId: LogicalServiceId

    A logical identifier unique in the deployment.

    A logical identifier unique in the deployment. Defaults to class name.

  14. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  15. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  16. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  17. final def synchronized[T0](arg0: ⇒ T0): T0
    Definition Classes
    AnyRef
  18. def toString(): String
    Definition Classes
    AnyRef → Any
  19. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  20. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  21. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... ) @native()
  22. object Instance

  23. object Envelope extends Serializable

    Definition Classes
    ServiceActor
  24. object Event

    Any statement in the protocol can be considered an Event not associated with any additional scope.

    Any statement in the protocol can be considered an Event not associated with any additional scope.

    - see also ServiceActor.RequestScope and Request.unapply

    Definition Classes
    ServiceActor
  25. object Request

    Definition Classes
    ServiceActor
  26. object StopEnvelope extends Envelope with Product with Serializable

    Definition Classes
    ServiceActor
  27. object Bindings

    Methods to bind this service's protocol to implementations.

    Methods to bind this service's protocol to implementations.

    If a binding is not provided for a protocol message the message is considered unhandled. Any endpoint for the protocol message will reply with HTTP 501 Not Implemented.

    // a hypothetical service for account balances
    final object AServiceFragment extends ServiceFragment {
    
      override def instantiate(env: InstanceEnv) = new Instance(env) {
        // the service event consumer is implemented using...
        val bindings = bindingsChain(
          // operations on a named entity
          entity(AnEntity) {
            case ServiceOperationOnEntity(entityId) => AnEntity.AnOperation -> accountId
          },
          // a daemon sending Proto messages back to this service
          async(OrdersOverSMSBehavior) // where OrdersOverSMSBehavior being a [[ServiceActorDaemon]]
        )
    }
    }
    Definition Classes
    ServiceBindings
  28. object Endpoints

    Definition Classes
    ServiceEndpoints

Inherited from ServiceEndpoints

Inherited from ActorService

Inherited from ServiceBindings

Inherited from ServiceActor

Inherited from AnyRef

Inherited from Any

Domain

Service Logic

Implementation Detail

Ungrouped