-
Notifications
You must be signed in to change notification settings - Fork 1
Application Core
A core3 application is made up of a number of components based on Akka Actors and they implement the core3.core.Component and core3.core.ComponentCompanion traits.
All of them can be managed by a core3.core.ComponentManager, normally configured in an app's Module definition. For example:
import akka.actor.ActorSystem
import akka.util.Timeout
import core3.config.StaticConfig
import com.google.inject.{AbstractModule, Provides, Singleton}
import core3.core.{ComponentManager, ComponentManagerActor}
import core3.database.dals.DatabaseAbstractionLayer
import core3.workflows.WorkflowEngine
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
class Module extends AbstractModule {
...
@Provides
@Singleton
def provideComponentManager(
system: ActorSystem,
engine: WorkflowEngine,
db: DatabaseAbstractionLayer
)(implicit ec: ExecutionContext): ComponentManager = {
val managerConfig = StaticConfig.get.getConfig("manager")
implicit val timeout = Timeout(
managerConfig.getInt("requestTimeout").seconds
)
new ComponentManager(
system.actorOf(
ComponentManagerActor.props(
Map(
"engine" -> engine.getRef,
"db" -> db.getRef
)
)
)
)
}
...
}In principle, only the Component trait needs to be extended, however, providing a ComponentCompanion object allows the CLI to integrate that component and process actions for it. Following is a simple example with two actions/commands:
import akka.actor.Props
import core3.core.{Component, ComponentCompanion}
import core3.core.Component.{ActionDescriptor, ActionResult}
import play.api.libs.json.Json
import scala.concurrent.{ExecutionContext, Future}
class TestComponent(implicit ec: ExecutionContext) extends Component {
//... some other definitions ...
private var count_ExecuteAction: Long = 0
override protected def shutdown(): Unit = {
//... some cleanup code (if required) ...
}
override protected def handle_ExecuteAction(
action: String,
params: Option[Map[String, Option[String]]]
): Future[ActionResult] = {
count_ExecuteAction += 1
Future {
action.toLowerCase match {
case "stats" =>
ActionResult(
wasSuccessful = true,
message = None,
data = Some(
Json.obj(
"counters" -> Json.obj(
"executeAction" -> count_ExecuteAction,
"anotherStat" -> "some value"
)
)
)
)
case "anotherAction" =>
ActionResult(
wasSuccessful = false,
message = Some("Not Implemented")
)
}
}
}
//... actual component implementation ...
}
object TestComponent extends ComponentCompanion {
def props()(implicit ec: ExecutionContext): Props = Props(
classOf[TestComponent], ec
)
//... other companion definitions ...
override def getActionDescriptors: Seq[ActionDescriptor] = {
Seq(
ActionDescriptor(
"stats",
"Retrieves the latest component stats",
arguments = None
),
ActionDescriptor(
"anotherAction",
"Some other action",
arguments = Some(Map("argName1" -> "(required) Required argument #1")))
)
}
}Allows the management of a core3-based application, when started in the foreground with the appropriate CLI flag (application-defined). For example (starts the core3-example-engine, with the console enabled):
sbt run -Dhttps.port=9900 -Dhttp.port=disabled -Dc3ee.console=enabled
Currently, the local console behaves normally only when the application is started directly with a jar and not via sbt / Play.
-
help- shows the help menu -
quit- terminates the application -
version- shows version information -
system- allows management of the application's core (configuration, state, etc)
Each component supplies it's own set of commands; see the running app's help menu for more information.
Creating the LocalConsole in a Play app requires two things: the console provider (in Module.scala) and a simple class to "require" that console.
import akka.actor.ActorSystem
import akka.util.Timeout
import com.google.inject.{AbstractModule, Provides, Singleton}
import core3.config.StaticConfig
import core3.core.Component.ComponentDescriptor
import core3.core.cli.LocalConsole
import core3.database._
import core3.database.dals.json.Redis
import core3.database.dals.DatabaseAbstractionLayer
import core3.workflows._
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
class Module extends AbstractModule {
//.. other providers ...
@Provides
@Singleton
def provideLocalConsole(
manager: ComponentManager,
engine: WorkflowEngine,
db: DatabaseAbstractionLayer
)(implicit ec: ExecutionContext): Option[LocalConsole] = {
Option(System.getProperty("c3ee.console")) match {
case Some("enabled") =>
val appVendor: String = core3_example_engine.BuildInfo.organization
val appName: String = core3_example_engine.BuildInfo.name
val appVersion: String = core3_example_engine.BuildInfo.version
val managerConfig = StaticConfig.get.getConfig("manager")
implicit val timeout = Timeout(
managerConfig.getInt("requestTimeout").seconds
)
Some(
LocalConsole(
appVendor,
appName,
appVersion,
manager.getRef,
Seq(
ComponentDescriptor(
"engine",
"The system's workflow engine",
core3.workflows.WorkflowEngineComponent
),
ComponentDescriptor(
"db",
"The system's core DB",
core3.database.dals.Core
),
ComponentDescriptor(
"bootstrap",
"The system's initializer",
BootstrapComponent
)
)
)
)
case _ => None
}
}
}import javax.inject.{Inject, Singleton}
import core3.core.cli.LocalConsole
import play.api.Environment
import scala.concurrent.{ExecutionContext, Future}
trait ConsoleStart
@Singleton
class ConsoleStartImpl @Inject()(
console: Option[LocalConsole]
)(implicit environment: Environment, ec: ExecutionContext)
extends ConsoleStart {
Future {
console.foreach(_.start())
}
}Home | Getting Started | Structure | Containers | Workflows | Controllers