Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance RestMulti, configurable demand + distinct objects #38801

Merged
merged 1 commit into from
Feb 16, 2024

Conversation

snazy
Copy link
Contributor

@snazy snazy commented Feb 15, 2024

Adds two enhancements:

  1. Produce multiple JSON objects, not just an array
  2. Make requested demand configurable

Produce multiple JSON objects

Currently, PublisherResponseHandler.StreamingMultiSubscriber produces a JSON array, where each emitted item is encoded as a JSON array element. For some use cases it is easier to consume a bunch of "bare" JSON objects - i.e. just write the individual JSON objects, possibly separated by a newline. As an option, of course.

Proposal to add:

RestMulti.fromMultiData(multi).encodeAsArray(false)...

With encodeAsArray(false), the produced JSON would look like this:

{"some": "value"}
{"some": "value"}
{"some": "value"}

encodeAsArray(true) or omitting it would use the current behavior and produce something like this:

[
{"some": "value"},
{"some": "value"},
{"some": "value"}
]

Configure request-demand

All implementations of PublisherResponseHandler.AbstractMultiSubscriber work with a hard-coded request-demand of 1, which means that every emitted item is "produced"/"computed" serially / one-after-the-other. If the computation of individual items takes somewhat longer, possibly waiting for remote resources to reply, it makes sense to use a higher demand to produce multiple items concurrently.

For example, if each item takes maybe 250 ms (requesting data from a remote source) to be produced, and 100 items are produced, it currently takes 25 seconds. With a higher concurrency it would take a fraction of that time. I.e. if the use case is known to be not CPU but (async) I/O bound, it might be legit/feasible to use a high demand.

Proposal to add:

RestMulti.fromMultiData(multi).withDemand( (long) 123 )...

Which would pass 123 as the demand for all call sites to Subscription.request in implementations of PublisherResponseHandler.AbstractMultiSubscriber.

@snazy
Copy link
Contributor Author

snazy commented Feb 15, 2024

@geoand there it is. Haven't added tests yet (hence it's still a draft-PR).

}
});
}
}

private static class ChunkedStreamingMultiSubscriber extends StreamingMultiSubscriber {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this inner class, because it's doing what StreamingMultiSubscriber does with encodeAsJsonArray==false

@geoand
Copy link
Contributor

geoand commented Feb 15, 2024

Nice!

@snazy snazy force-pushed the rest-multi-enhancements branch from 6db9089 to b2dd31d Compare February 15, 2024 17:57
@snazy snazy marked this pull request as ready for review February 15, 2024 17:57
@snazy
Copy link
Contributor Author

snazy commented Feb 15, 2024

Added test cases and updated docs

@snazy snazy force-pushed the rest-multi-enhancements branch from b2dd31d to 1cfe6f5 Compare February 15, 2024 18:00

This comment has been minimized.

This comment has been minimized.

Copy link

github-actions bot commented Feb 15, 2024

🙈 The PR is closed and the preview is expired.

Adds two enhancements:

1. Produce multiple JSON objects, not just an array
2. Make requested demand configurable

== Produce multiple JSON objects

Currently, `PublisherResponseHandler.StreamingMultiSubscriber` produces a JSON array, where each emitted item is encoded as a JSON array element. For some use cases it is easier to consume a bunch of "bare" JSON objects - i.e. just write the individual JSON objects, possibly separated by a newline. As an option, of course.

Proposal to add:
```java
RestMulti.fromMultiData(multi).encodeAsArray(false)...
```

With `encodeAsArray(false)`, the produced JSON would look like this:
```json
{"some": "value"}
{"some": "value"}
{"some": "value"}
```

`encodeAsArray(true)` or omitting it would use the current behavior and produce something like this:
```json
[{"some": "value"},
{"some": "value"},
{"some": "value"}
}
```

== Configure request-demand

All implementations of `PublisherResponseHandler.AbstractMultiSubscriber` work with a hard-coded request-demand of `1`, which means that every emitted item is "produced"/"computed" serially / one-after-the-other. If the computation of individual items takes somewhat longer, possibly waiting for remote resources to reply, it makes sense to use a higher demand to produce multiple items concurrently.

For example, if each item takes maybe 250 ms (requesting data from a remote source) to be produced, and 100 items are produced, it currently takes 25 seconds. With a higher concurrency it would take a fraction of that time. I.e. if the use case is known to be not CPU but (async) I/O bound, it _might_ be legit/feasible to use a high demand.

Proposal to add:
```
RestMulti.fromMultiData(multi).withDemand( (long) 123 )...
```

Which would pass `123` as the demand for all call sites to `Subscription.request` in implementations of `PublisherResponseHandler.AbstractMultiSubscriber`.
@snazy snazy force-pushed the rest-multi-enhancements branch from 1cfe6f5 to 0b1bf99 Compare February 15, 2024 19:29
Copy link

quarkus-bot bot commented Feb 15, 2024

Status for workflow Quarkus Documentation CI

This is the status report for running Quarkus Documentation CI on commit 0b1bf99.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

⚠️ There are other check runs running, make sure you don't need to wait for their status before merging.

Copy link

quarkus-bot bot commented Feb 15, 2024

Status for workflow Quarkus CI

This is the status report for running Quarkus CI on commit 0b1bf99.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.


Flaky tests - Develocity

⚙️ JVM Tests - JDK 17

📦 extensions/smallrye-reactive-messaging-kafka/deployment

io.quarkus.smallrye.reactivemessaging.kafka.deployment.dev.KafkaDevServicesDevModeTestCase.sseStream - History

  • Assertion condition defined as a io.quarkus.smallrye.reactivemessaging.kafka.deployment.dev.KafkaDevServicesDevModeTestCase Expecting size of: [] to be greater than or equal to 2 but was 0 within 10 seconds. - org.awaitility.core.ConditionTimeoutException
org.awaitility.core.ConditionTimeoutException: 
Assertion condition defined as a io.quarkus.smallrye.reactivemessaging.kafka.deployment.dev.KafkaDevServicesDevModeTestCase 
Expecting size of:
  []
to be greater than or equal to 2 but was 0 within 10 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)

Copy link
Contributor

@geoand geoand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lovely!

@geoand geoand merged commit e97f3e2 into quarkusio:main Feb 16, 2024
45 checks passed
@quarkus-bot quarkus-bot bot added this to the 3.9 - main milestone Feb 16, 2024
@snazy snazy deleted the rest-multi-enhancements branch February 16, 2024 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

2 participants