Skip to content

Commit

Permalink
Trigger service docs and SDK integration basics (digital-asset#6329)
Browse files Browse the repository at this point in the history
* Integrate trigger-service into the assistant

changelog_begin
changelog_end

* Assistant integration and bare bones docs

changelog_begin
changelog_end
  • Loading branch information
shayne-fletcher authored Jun 12, 2020
1 parent 087d03f commit 23e7dc8
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 4 deletions.
1 change: 1 addition & 0 deletions daml-assistant/daml-sdk/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ da_scala_library(
"//ledger/sandbox",
"//navigator/backend:navigator-library",
"//triggers/runner:trigger-runner-lib",
"//triggers/service:trigger-service",
"@maven//:com_typesafe_akka_akka_http_spray_json_2_12",
"@maven//:com_typesafe_scala_logging_scala_logging_2_12",
"@maven//:io_spray_spray_json_2_12",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package com.daml.sdk
import com.daml.codegen.{CodegenMain => Codegen}
import com.daml.lf.engine.script.{RunnerMain => Script, TestMain => TestScript}
import com.daml.lf.engine.trigger.{RunnerMain => Trigger}
import com.daml.lf.engine.trigger.{ServiceMain => TriggerService}
import com.daml.extractor.{Main => Extractor}
import com.daml.http.{Main => JsonApi}
import com.daml.navigator.{NavigatorBackend => Navigator}
Expand All @@ -23,6 +24,7 @@ object SdkMain {
case "codegen" => Codegen.main(rest)
case "extractor" => Extractor.main(rest)
case "json-api" => JsonApi.main(rest)
case "trigger-service" => TriggerService.main(rest)
case "navigator" => Navigator.main(rest)
case "sandbox" => Sandbox.main(rest)
case "sandbox-classic" => SandboxClassic.main(rest)
Expand Down
2 changes: 1 addition & 1 deletion daml-assistant/exe/DA/Daml/Assistant.hs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ argWhitelist = S.fromList
, "codegen", "java", "scala", "js"
, "deploy"
, "json-api"
, "trigger", "list"
, "trigger", "trigger-service", "list"
, "script"
, "test-script"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,28 @@ quickstartTests quickstartDir mvnDir = testGroup "quickstart"
-- waitForProcess' will block on Windows so we explicitly kill the process.
terminateProcess jsonApiPh
terminateProcess sandboxPh
, testCase "trigger service startup" $
withCurrentDirectory quickstartDir $
withDevNull $ \devNull1 -> do
withDevNull $ \devNull2 -> do
withDevNull $ \devNull3 -> do
sandboxPort :: Int <- fromIntegral <$> getFreePort
let sandboxProc = (shell $ unwords ["daml", "sandbox", "--wall-clock-time", "--port", show sandboxPort, ".daml/dist/quickstart-0.0.1.dar"]) { std_out = UseHandle devNull1, std_in = CreatePipe }
withCreateProcess sandboxProc $ \_ _ _ sandboxPh -> race_ (waitForProcess' sandboxProc sandboxPh) $ do
waitForConnectionOnPort (threadDelay 100000) sandboxPort
triggerServicePort :: Int <- fromIntegral <$> getFreePort
let triggerServiceProc = (shell $ unwords ["daml", "trigger-service", "--ledger-host", "localhost", "--ledger-port", show sandboxPort, "--http-port", show triggerServicePort, "--wall-clock-time", "--no-secret-key"]) { std_out = UseHandle devNull2, std_err = UseHandle devNull3, std_in = CreatePipe }
withCreateProcess triggerServiceProc $ \_ _ _ triggerServicePh -> race_ (waitForProcess' triggerServiceProc triggerServicePh) $ do
let endpoint = "http://localhost:" <> show triggerServicePort <> "/v1/health"
waitForHttpServer (threadDelay 100000) endpoint []
req <- parseRequest endpoint
manager <- newManager defaultManagerSettings
resp <- httpLbs req manager
responseBody resp @?= "{\"status\":\"pass\"}"
-- waitForProcess' will block on Windows so we
-- explicitly kill the process.
terminateProcess triggerServicePh
terminateProcess sandboxPh
, testCase "mvn compile" $
withCurrentDirectory quickstartDir $ do
mvnDbTarball <- locateRunfiles (mainWorkspace </> "daml-assistant" </> "integration-tests" </> "integration-tests-mvn.tar")
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ DAML SDK documentation
triggers/index
daml-repl/index
tools/visual
tools/trigger-service

.. toctree::
:titlesonly:
Expand Down
113 changes: 113 additions & 0 deletions docs/source/tools/trigger-service.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
.. Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
.. SPDX-License-Identifier: Apache-2.0
Trigger Service
###############

**WARNING:** The Trigger Service is an early access feature that is actively being designed and is *subject to breaking changes*. The documentation here at this time is limited to basic usage. As more features become available the documentation will be updated to include them. We welcome feedback about the Trigger Service on our `our issue tracker <https://github.com/digital-asset/daml/issues/new>`_ or `on our forum <https://discuss.daml.com>`_, or on `on Slack <https://slack.daml.com>`_.

The `DAML triggers <../triggers/index.html#running-a-daml-trigger>`_ documentation shows a simple method using the ``daml trigger`` command to arrange for the execution of a single trigger. Using this method, a dedicated process is launched to host the trigger.

Complex workflows can require running many triggers for many parties and at a certain point, use of ``daml trigger`` with its process per trigger model becomes unwieldy. The Trigger Service provides the means to host multiple triggers for multiple parties running against a common ledger in a single process and provides a convenient interface for starting, stopping and monitoring them.

The trigger-service is a ledger client that acts as an end-user agent. The trigger service intermediates between the ledger and end-users by running triggers on their behalf. The trigger-service is an HTTP REST service. All requests and responses use JSON to encode data.

Starting the Trigger Service
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In this example, it is assumed there is a sandbox ledger running on port 6865 on localhost.

.. code-block:: bash
daml trigger-service --ledger-host localhost --ledger-port 6865 --wall-clock-time --no-secret-key
The above starts the Trigger Service using a number of default parameters. Most notably, the HTTP port the Trigger Service listens on which defaults to 8088. The meaning of the ``--no-secret-key`` parameter will be explained in a later section. To see all of the available parameters, their defaults and descriptions, one can execute the command ``daml trigger-service --help``.

Although as we'll see, the Trigger Service exposes an endpoint for end-users to upload DAR files to the service it is sometimes convenient to start the service pre-configured with a specific DAR. To do this, the ``--dar`` option is provided.

.. code-block:: bash
daml trigger-service --ledger-host localhost --ledger-port 6865 --wall-clock-time --no-secret-key --dar <DAR>
End-user interaction with the Trigger Service
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``start``
*********

Start a trigger. In this example, Alice starts the trigger called ``trigger`` in a module called ``TestTrigger`` of a package with ID ``312094804c1468e2166bae3c9ba8b5cc0d285e31356304a2e9b0ac549df59d14``. The response contains an identifier for the running trigger that Alice can use in subsequent commands involving the trigger.

.. code-block:: bash
$curl --user 'alice:secret' \
-X POST localhost:8088/v1/start \
-H "Content-type: application/json" -H "Accept: application/json" \
-d '{"triggerName":"312094804c1468e2166bae3c9ba8b5cc0d285e31356304a2e9b0ac549df59d14:TestTrigger:trigger"}'
{"result":{"triggerId":"4d539e9c-b962-4762-be71-40a5c97a47a6"},"status":200}
``stop``
********

Stop a running trigger. Alice stops her running trigger like so.

.. code-block:: bash
$curl --user 'alice:secret' \
-X DELETE localhost:8088/v1/stop/4d539e9c-b962-4762-be71-40a5c97a47a6 \
-H "Content-type: application/json" -H "Accept: application/json"
{"result":{"triggerId":"4d539e9c-b962-4762-be71-40a5c97a47a6"},"status":200}
``upload_dar``
**************

Upload an automation DAR. If successful, the DAR's "main package ID" will be in the response (the main package ID for a DAR can also be obtained using ``daml damlc inspect-dar path/to/dar``).

.. code-block:: bash
$ curl -F 'dar=@/home/alice/test-model.dar' localhost:8088/v1/upload_dar
{"result":{"mainPackageId":"312094804c1468e2166bae3c9ba8b5cc0d285e31356304a2e9b0ac549df59d14"},"status":200}
``list``
********

List the DARS running on behalf of a given party. Alice can check on her running triggers as follows.

.. code-block:: bash
$curl --user 'alice:secret' \
-X GET localhost:8088/v1/list \
-H "Content-type: application/json" -H "Accept: application/json"
{"result":{"triggerIds":["4d539e9c-b962-4762-be71-40a5c97a47a6"]}
``status``
**********

It's sometimes useful to get information about the history of a specific trigger. This can be done with the "status" endpoint.

.. code-block:: bash
$curl --user 'alice:secret' \
-X GET localhost:8088/v1/status/4d539e9c-b962-4762-be71-40a5c97a47a6 \
-H "Content-type: application/json" -H "Accept: application/json"
{"result":{"logs":[["2020-06-12T12:35:49.863","starting"],["2020-06-12T12:35:50.89","running"],["2020-06-12T12:51:57.557","stopped: by user request"]]},"status":200}
``health``
**********

Test connectivity.

.. code-block:: bash
$curl -X GET localhost:8088/v1/health
{"status":"pass"}
Identifying trigger parties
~~~~~~~~~~~~~~~~~~~~~~~~~~~

In this section, we briefly explain how parties are identified in end-user interactions with a running Trigger Service.

When an end-user interacts with a Trigger Service, they do so by sending HTTP requests to one of several Trigger Service HTTP endpoints. Such requests must contain information detailing the party the Trigger Service is to act on the behalf of in its handling of the user request.

This party information is conveyed via HTTP basic authentication headers where the requesting party is represented by a unique username/password pair (for now passwords must be provided but are ignored - future versions will support authentication and validation).

With an understanding of the role of credentials now in mind we can explain the ``--no-secret-key`` Trigger Service option. When the Trigger Service stores credentials it first encrypts them. The encryption/decryption algorithms it uses to do so require the use of a "key". What key is to be used is expected to be provided as the value of the environment variable ``TRIGGER_SERVICE_SECRET_KEY`` (for example, before starting the Trigger Service by a command like ``export TRIGGER_SERVICE_SECRET_KEY="my secret key"``). At startup, if the Trigger Service detects that the environment variable is not defined then it will terminate unless the parameter ``--no-secret-key`` is in its startup options. If it is, the service will continue with a default key.
1 change: 0 additions & 1 deletion release/artifacts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,3 @@
type: jar-scala
- target: //libs-scala/build-info:build-info
type: jar-scala

4 changes: 4 additions & 0 deletions release/sdk-config.yaml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ commands:
path: daml-helper/daml-helper
desc: "Launch the HTTP JSON API"
args: ["run-jar", "--logback-config=daml-sdk/json-api-logback.xml", "daml-sdk/daml-sdk.jar", "json-api"]
- name: trigger-service
path: daml-helper/daml-helper
desc: "Launch the trigger service"
args: ["run-jar", "--logback-config=daml-sdk/trigger-service-logback.xml", "daml-sdk/daml-sdk.jar", "trigger-service"]
- name: trigger
path: daml-helper/daml-helper
args: ["run-jar", "--logback-config=daml-sdk/trigger-logback.xml", "daml-sdk/daml-sdk.jar", "trigger"]
Expand Down
2 changes: 2 additions & 0 deletions release/util.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def sdk_tarball(name, version):
"//navigator/backend:src/main/resources/logback.xml",
"//extractor:src/main/resources/logback.xml",
"//ledger-service/http-json:release/json-api-logback.xml",
"//triggers/service:release/trigger-service-logback.xml",
"//language-support/java/codegen:src/main/resources/logback.xml",
"//triggers/runner:src/main/resources/logback.xml",
"//daml-script/runner:src/main/resources/logback.xml",
Expand Down Expand Up @@ -69,6 +70,7 @@ def sdk_tarball(name, version):
mkdir -p $$OUT/daml-sdk
cp $(location //daml-assistant/daml-sdk:sdk_deploy.jar) $$OUT/daml-sdk/daml-sdk.jar
cp -L $(location //ledger-service/http-json:release/json-api-logback.xml) $$OUT/daml-sdk/
cp -L $(location //triggers/service:release/trigger-service-logback.xml) $$OUT/daml-sdk/
cp -L $(location //ledger/sandbox:src/main/resources/logback.xml) $$OUT/daml-sdk/sandbox-logback.xml
cp -L $(location //navigator/backend:src/main/resources/logback.xml) $$OUT/daml-sdk/navigator-logback.xml
cp -L $(location //extractor:src/main/resources/logback.xml) $$OUT/daml-sdk/extractor-logback.xml
Expand Down
4 changes: 2 additions & 2 deletions triggers/service/daml-platform.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ done
echo "Connected to sandbox."

bazel run //triggers/service:trigger-service-binary -- \
--http-port $TRIGGER_SERVICE_HTTP_PORT --ledger-host $LEDGER_HOST --ledger-port $LEDGER_PORT --wall-clock-time &
TRIGGER_SERVICE_PID=$!
--http-port $TRIGGER_SERVICE_HTTP_PORT --ledger-host $LEDGER_HOST --ledger-port $LEDGER_PORT --no-secret-key
$LEDGER_TRIGGER_SERVICE_PID=$!

# Requests to the trigger service need an HTTP basic authorization
# header.
Expand Down

0 comments on commit 23e7dc8

Please sign in to comment.