如何使用单个POST API调用执行多个并行操作?

时间:2016-06-06 16:55:48

标签: api post groovy cassandra ratpack

我使用Ratpack和Groovy创建了一个API。我想要一个POST API,以便处理数据并将其存储在2个cassandra数据库中,例如table-A和table-B。 现在我在我的Ratpack.groovy中有这个,因此每当必须推送数据时我都必须调用两个API:

prefix("A") {
    post {  registry.get(PostEndpointA).handle(context) }
}
prefix("B") {
    post {  registry.get(PostEndpointB).handle(context) }
}

我想要一个这样的POST API调用,这样通过单个API调用,请求可以一起委托给两个端点:

prefix("post") {
    post {  registry.get(PostEndpointA).handle(context) }
    post {  registry.get(PostEndpointB).handle(context) }
}

或者,我想要这个:

prefix("post") {
        post {  registry.get(PostEndpoint).handle(context) }
}

在PostEndpoint中,我可以执行以下操作:

saveJsonAsA(context)
            .promiseSingle()
            .then { ItemA updatedItem ->
                context.response.headers
                    .add(HttpHeaderNames.LOCATION, "/item/api/A")
                context.response.status(HttpResponseStatus.CREATED.code())
                    .send()
            }
saveJsonAsB(context)
            .promiseSingle()
            .then { ItemB updatedItem ->
                context.response.headers
                    .add(HttpHeaderNames.LOCATION, "/item/api/B")
                context.response.status(HttpResponseStatus.CREATED.code())
                    .send()
            }

在这两种情况下,该项目仅添加到表格A而不是B或之前在代码中写入的任何内容。

注意,ItemA和ItemB与基本相同的DB相关,只有主键不同,以便从2种方式促进GET。知道如何在Ratpack中做到这一点?

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你可以尝试做类似的事情:

@Grab('io.ratpack:ratpack-groovy:1.3.3')

import static ratpack.groovy.Groovy.ratpack

import ratpack.http.Status
import ratpack.exec.Promise
import com.google.common.reflect.TypeToken

class ServiceA {
  Promise<String> save(json) {
    Promise.value(json)
  }
}

class ServiceB {
  Promise<String> save(json) {
    Promise.value(json)
  }
}

ratpack {
  bindings {
    bindInstance new ServiceA()
    bindInstance new ServiceB()
  }
  handlers {
    post(':name') { // parameterize on path token
      def name = pathTokens.get('name') // extract token
      def service = null
      switch(name) {
        case 'A':
          service = get(ServiceA) // extract appropriate service
          break
        case 'B':
          service = get(ServiceB) // extract appropriate service
          break
      }

      parse(new TypeToken<Map<String, Object>>(){})
        .flatMap(service.&save) // save your extracted item
        .then {
          response.headers.add('Location', "/item/api/$name")
          response.status(Status.of(201))
          response.send()
        }
    }
  }
}

样品卷发看起来像这样

$ curl -X POST -H'Content-Type: application/json' -d '{"foo":"bar"}' -v localh ost:5050/A

< HTTP/1.1 201 Created
< Location: /item/api/A
< content-length: 0
< connection: keep-alive

$ curl -X POST -H'Content-Type: application/json' -d '{"foo":"bar"}' -v localh ost:5050/B

< HTTP/1.1 201 Created
< Location: /item/api/B
< content-length: 0
< connection: keep-alive

根据您发布的问题数量,我建议您注册Ratpack社区冗余频道https://slack-signup.ratpack.io/

答案 1 :(得分:0)

我们使用rxJava来执行此操作: Single .zip( service.add(cv1), service.add(cv2), (a, b) -> new Object[] { a, b } ) .blockingGet(); 我们将它包装在一个promise中并处理then块中的数组。