Trigger service: use "triggerId" and "triggerIds" fields for response messages (#5854)

* Use triggerId field in trigger start response

* Use triggerId field for stop trigger result

* Fix indentation and make yields consistent

* Use pair constructor for JsObject instead of Map

* Use triggerIds field in list triggers response

changelog_begin
changelog_end
This commit is contained in:
Rohan Jacob-Rao 2020-05-06 11:44:07 -04:00 committed by GitHub
parent 9ebfd01f83
commit 4797834e1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 41 deletions

View File

@ -31,6 +31,7 @@ import scala.util.{Failure, Success}
import scalaz.syntax.tag._
import scalaz.syntax.traverse._
import spray.json.DefaultJsonProtocol._
import spray.json._
import com.daml.lf.CompiledPackages
import com.daml.lf.archive.{Dar, DarReader, Decode}
import com.daml.lf.archive.Reader.ParseError
@ -57,7 +58,6 @@ import com.daml.ledger.client.configuration.{
import com.daml.lf.engine.trigger.Request.{ListParams, StartParams}
import com.daml.lf.engine.trigger.Response._
import com.daml.platform.services.time.TimeProviderType
import spray.json.{JsObject, JsString}
case class LedgerConfig(
host: String,
@ -246,7 +246,8 @@ object Server {
triggers = triggers + (uuid -> TriggerActorWithParty(ref, party))
val newTriggerSet = triggersByParty.getOrElse(party, Set()) + uuid
triggersByParty = triggersByParty + (party -> newTriggerSet)
complete(successResponse(uuid.toString))
val triggerIdResult = JsObject(("triggerId", uuid.toString.toJson))
complete(successResponse(triggerIdResult))
}
}
},
@ -269,8 +270,7 @@ object Server {
case (pkgId, payload) => Decode.readArchivePayload(pkgId, payload)
}
addDar(compiledPackages, dar)
val mainPackageId =
JsObject(Map() + ("mainPackageId" -> JsString(dar.main._1)))
val mainPackageId = JsObject(("mainPackageId", dar.main._1.name.toJson))
complete(successResponse(mainPackageId))
} catch {
case err: ParseError =>
@ -289,21 +289,23 @@ object Server {
{
val triggerList =
triggersByParty.getOrElse(params.party, Set()).map(_.toString).toList
complete(successResponse(triggerList))
val result = JsObject(("triggerIds", triggerList.toJson))
complete(successResponse(result))
}
}
}
},
// Stop a trigger given its UUID
delete {
pathPrefix("stop" / JavaUUID) { id =>
val actorWithParty = triggers.get(id).get
pathPrefix("stop" / JavaUUID) { uuid =>
val actorWithParty = triggers.get(uuid).get
actorWithParty.ref ! TriggerActor.Stop
triggers = triggers - id
triggers = triggers - uuid
val party = actorWithParty.party
val newTriggerSet = triggersByParty.get(party).get - id
val newTriggerSet = triggersByParty.get(party).get - uuid
triggersByParty = triggersByParty + (party -> newTriggerSet)
complete(successResponse(s"Trigger $id has been stopped."))
val stoppedTriggerId = JsObject(("triggerId", uuid.toString.toJson))
complete(successResponse(stoppedTriggerId))
}
},
)

View File

@ -130,10 +130,22 @@ class ServiceTest extends AsyncFlatSpec with Eventually with Matchers {
def parseTriggerId(resp: HttpResponse): Future[String] = {
for {
JsString(triggerId) <- parseResult(resp)
JsObject(fields) <- parseResult(resp)
Some(JsString(triggerId)) = fields.get("triggerId")
} yield triggerId
}
def parseTriggerIds(resp: HttpResponse): Future[Vector[String]] = {
for {
JsObject(fields) <- parseResult(resp)
Some(JsArray(ids)) = fields.get("triggerIds")
triggerIds = ids map {
case JsString(id) => id
case _ => fail("""Non-string element of "triggerIds" field""")
}
} yield triggerIds
}
it should "fail to start non-existent trigger" in withHttpService(Some(dar)) {
(uri: Uri, client) =>
val expectedError = StatusCodes.UnprocessableEntity
@ -160,12 +172,12 @@ class ServiceTest extends AsyncFlatSpec with Eventually with Matchers {
triggerId <- parseTriggerId(resp)
resp <- listTriggers(uri, "Alice")
result <- parseResult(resp)
_ <- result should equal(JsArray(JsString(triggerId)))
result <- parseTriggerIds(resp)
_ <- result should equal(Vector(triggerId))
resp <- stopTrigger(uri, triggerId)
JsString(result) <- parseResult(resp)
_ <- result should equal(s"Trigger $triggerId has been stopped.")
stoppedTriggerId <- parseTriggerId(resp)
_ <- stoppedTriggerId should equal(triggerId)
} yield succeed
}
@ -174,43 +186,43 @@ class ServiceTest extends AsyncFlatSpec with Eventually with Matchers {
for {
// no triggers running initially
resp <- listTriggers(uri, "Alice")
result <- parseResult(resp)
_ <- result should equal(JsArray())
result <- parseTriggerIds(resp)
_ <- result should equal(Vector())
// start trigger for Alice
resp <- startTrigger(uri, s"$testPkgId:TestTrigger:trigger", "Alice")
aliceTrigger <- parseTriggerId(resp)
resp <- listTriggers(uri, "Alice")
result <- parseResult(resp)
_ <- result should equal(JsArray(JsString(aliceTrigger)))
result <- parseTriggerIds(resp)
_ <- result should equal(Vector(aliceTrigger))
// start trigger for Bob
resp <- startTrigger(uri, s"$testPkgId:TestTrigger:trigger", "Bob")
bobTrigger1 <- parseTriggerId(resp)
resp <- listTriggers(uri, "Bob")
result <- parseResult(resp)
_ <- result should equal(JsArray(JsString(bobTrigger1)))
result <- parseTriggerIds(resp)
_ <- result should equal(Vector(bobTrigger1))
// start another trigger for Bob
resp <- startTrigger(uri, s"$testPkgId:TestTrigger:trigger", "Bob")
bobTrigger2 <- parseTriggerId(resp)
resp <- listTriggers(uri, "Bob")
result <- parseResult(resp)
_ <- result should equal(JsArray(JsString(bobTrigger1), JsString(bobTrigger2)))
result <- parseTriggerIds(resp)
_ <- result should equal(Vector(bobTrigger1, bobTrigger2))
// stop Alice's trigger
resp <- stopTrigger(uri, aliceTrigger)
_ <- assert(resp.status.isSuccess)
resp <- listTriggers(uri, "Alice")
result <- parseResult(resp)
_ <- result should equal(JsArray())
result <- parseTriggerIds(resp)
_ <- result should equal(Vector())
resp <- listTriggers(uri, "Bob")
result <- parseResult(resp)
_ <- result should equal(JsArray(JsString(bobTrigger1), JsString(bobTrigger2)))
result <- parseTriggerIds(resp)
_ <- result should equal(Vector(bobTrigger1, bobTrigger2))
// stop Bob's triggers
resp <- stopTrigger(uri, bobTrigger1)
_ <- assert(resp.status.isSuccess)
resp <- stopTrigger(uri, bobTrigger2)
_ <- assert(resp.status.isSuccess)
resp <- listTriggers(uri, "Bob")
result <- parseResult(resp)
_ <- result should equal(JsArray())
result <- parseTriggerIds(resp)
_ <- result should equal(Vector())
} yield succeed
}
@ -237,19 +249,20 @@ class ServiceTest extends AsyncFlatSpec with Eventually with Matchers {
}
// Query ACS until we see a B contract
// format: off
_ <- Future {
val filter = TransactionFilter(List(("Alice", Filters(Some(InclusiveFilters(Seq(Identifier(testPkgId, "TestTrigger", "B"))))))).toMap)
eventually {
val acs = client.activeContractSetClient.getActiveContracts(filter).runWith(Sink.seq)
.map(acsPages => acsPages.flatMap(_.activeContracts))
// Once we switch to scalatest 3.1, we should no longer need the Await.result here since eventually
// handles Future results.
val r = Await.result(acs, Duration.Inf)
assert(r.length == 1)
_ <- Future {
val filter = TransactionFilter(List(("Alice", Filters(Some(InclusiveFilters(Seq(Identifier(testPkgId, "TestTrigger", "B"))))))).toMap)
eventually {
val acs = client.activeContractSetClient.getActiveContracts(filter).runWith(Sink.seq)
.map(acsPages => acsPages.flatMap(_.activeContracts))
// Once we switch to scalatest 3.1, we should no longer need the Await.result here since eventually
// handles Future results.
val r = Await.result(acs, Duration.Inf)
assert(r.length == 1)
}
}
}
// format: on
// format: on
resp <- stopTrigger(uri, triggerId)
} yield assert(resp.status.isSuccess)
_ <- assert(resp.status.isSuccess)
} yield succeed
}
}