【问题标题】:How to perform multiple parallel operations using a single POST API Call?如何使用单个 POST API 调用执行多个并行操作?
【发布时间】:2016-06-06 16:55:47
【问题描述】:

我使用 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,只是主键不同,方便两种方式的GET。知道如何在 Ratpack 中执行此操作吗?

【问题讨论】:

  • 您能否将您的要求作为一系列请求/响应预期提供?那是 POST /endpointA -> 应该发生一些事情 POST /endpointB -> 其他事情 GET /endpointA -> 更多事情
  • POST: endpointA -> 解析请求 JSON 并将对象保存到表 A.endpointB -> 解析请求 JSON 并将对象保存到表 B. GET: /api/A/123 ->从标识符 = 123 /api/B/123 的表 A 返回所有属性 -> 从标识符 = 123 的表 A 返回所有属性 GET 部分没问题,但我在处理多个 POST 部分时遇到问题。
  • 谁能帮我解决这个问题?

标签: api post groovy cassandra ratpack


【解决方案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 社区 slack 频道 https://slack-signup.ratpack.io/

【讨论】:

  • 我加入了 Ratpack 社区 Slack 频道。这对您的努力和时间来说是很多的,您的解决方案真的很有帮助,我以后可以使用。但就目前而言,这不是我的问题。我想总是 POST 到 2 个不同的表,它不依赖于条件。我的意思是每当有任何 POST API 调用时,都应该将数据写入表 A 和 B。现在,它不是将数据写入两个表,但是如果插入表 A 的代码/处理程序是较早编写的,则只有正在插入 A 而不是 B。
  • 我会看看 rxJava/rxGroovy 的 Observable.zip()。这就是 netflix 使用的。
【解决方案2】:

我们使用 rxJava 来做到这一点: Single .zip( service.add(cv1), service.add(cv2), (a, b) -> new Object[] { a, b } ) .blockingGet(); 我们将其包装在一个 Promise 中并在 then 块中处理该数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多