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

JAMES-2813 Add non-polling and timeout on TaskManager.await #2653

Closed
wants to merge 13 commits into from

Conversation

blackheaven
Copy link

No description provided.

@ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The taskId is not found")
@ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The taskId is invalid or invalid timeout"),
@ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The taskId is not found"),
@ApiResponse(code = HttpStatus.REQUEST_TIMEOUT_408, message = "The timeout have been reached")
Copy link
Member

Choose a reason for hiding this comment

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

s/have/has

ErrorResponder.builder()
.statusCode(HttpStatus.REQUEST_TIMEOUT_408)
.type(ErrorResponder.ErrorType.SERVER_ERROR)
.message("The timeout have been reached")
Copy link
Member

Choose a reason for hiding this comment

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

s/have/has

.queryParam("timeout", "5")
.when()
.get("/" + taskId.getValue() + "/await")
.then()
Copy link
Member

Choose a reason for hiding this comment

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

Indent


given()
.queryParam("timeout", "-5")
.when()
Copy link
Member

Choose a reason for hiding this comment

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

Indent

Copy link
Member

Choose a reason for hiding this comment

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

That went back somehow in one of your fixup?

Copy link
Author

Choose a reason for hiding this comment

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

a github bug I think

.queryParam("timeout", "-5")
.when()
.get("/" + taskId.getValue() + "/await")
.then()
Copy link
Member

Choose a reason for hiding this comment

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

Indent

Copy link
Member

Choose a reason for hiding this comment

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

That went back somehow in one of your fixup?


given()
.queryParam("timeout", "2")
.when()
Copy link
Member

Choose a reason for hiding this comment

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

Indent

.queryParam("timeout", "2")
.when()
.get("/" + taskId.getValue() + "/await")
.then()
Copy link
Member

Choose a reason for hiding this comment

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

Indent

void getAwaitWithANonExistingTaskShouldReturnNotFound() {
when()
.get("/" + TaskId.generateTaskId().asString() + "/await")
.then()
Copy link
Member

Choose a reason for hiding this comment

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

Indent

}

@Test
default void awaitANonExistingTaskShouldReturnAUnknownAwaitedTaskExecutionDetailsAndThrow() {
Copy link
Member

Choose a reason for hiding this comment

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

s/AUnknown/AnUnknown

@Arsnael
Copy link
Member

Arsnael commented Aug 30, 2019

[235366ef6e4e04ad3005692b8272b7ab43b89696] [INFO] There is 1 error reported by Checkstyle 8.18 with checkstyle.xml ruleset.
[235366ef6e4e04ad3005692b8272b7ab43b89696] [ERROR] src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java:[29,8] (imports) UnusedImports: Unused import - org.apache.commons.lang3.NotImplementedException.

.orElse(Long.MAX_VALUE / 1000);

Preconditions.checkState(value > 0);
return Duration.ofSeconds(value);

Choose a reason for hiding this comment

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

why do you divide by 1000 and the take a Duration.ofSeconds? You could directly take a Duration.ofMillis, no?

Choose a reason for hiding this comment

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

ok I got the explanation, but the readability is not very clear. If you name Long.MAX_VALUE as a constant, it would be better.

Copy link
Author

Choose a reason for hiding this comment

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

The unit in the API is seconds and the maximal value of Duration is Duration.ofMillis(Long.MAX_VALUE), I'm forced to divide to avoid overflows.

Choose a reason for hiding this comment

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

Who will need to wait an HTTP request for 106751991167300 days? What if you assert a max value of 1 day for example?

Choose a reason for hiding this comment

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

BTW, there's no test to check this "feature"

Copy link
Author

Choose a reason for hiding this comment

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

TasksRoutesTests.getAwaitWithInvalidTimeoutShouldReturnAnError()

I prefer let the user the choice

Choose a reason for hiding this comment

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

It doesn't check that you can put 106751991167300 days

@@ -3269,16 +3269,17 @@ One can await the end of a task, then receive it's final execution report.
That feature is especially usefull for testing purpose but still can serve real-life scenari.

```
curl -XGET http://ip:port/tasks/3294a976-ce63-491e-bd52-1b6f465ed7a2/await
curl -XGET http://ip:port/tasks/3294a976-ce63-491e-bd52-1b6f465ed7a2/await?timeout=numberOfSeconds

Choose a reason for hiding this comment

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

as you divide by 1000 it's millis, no?
BTW what about allowing some timeunit here? I guess we already have all the needed available code for that.

Copy link
Author

Choose a reason for hiding this comment

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

I've found nothing regarding that.

Anyway, I think it clearly not worth the time and effort maintaining such code and a decent suite of tests.

Copy link
Member

Choose a reason for hiding this comment

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

Is that new timeout parameter now compulsory?

Choose a reason for hiding this comment

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

org.apache.james.util.DurationParser?

Copy link
Author

Choose a reason for hiding this comment

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

Is that new timeout parameter now compulsory?

no

Copy link
Author

Choose a reason for hiding this comment

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

org.apache.james.util.DurationParser?

spaces are mandatory, it look likes a bad idea

Copy link

Choose a reason for hiding this comment

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

that's not how I read it. But maybe some missing tests

@rouazana
Copy link

[a00bcb5801ef53778c791f98b374a1c8c0759985] [ERROR] src/main/java/org/apache/james/DistributedTaskManagerModule.java:[26,8] (imports) UnusedImports: Unused import - org.apache.james.task.eventsourcing.MemoryTerminationSubscriber.

@ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The taskId is not found")
@ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The taskId is invalid or invalid timeout"),
@ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The taskId is not found"),
@ApiResponse(code = HttpStatus.REQUEST_TIMEOUT_408, message = "The timeout have been reached")

Choose a reason for hiding this comment

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

do you think the message add anything?

Copy link
Author

Choose a reason for hiding this comment

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

sure, because it specifies the cause of the request timeout

Copy link

@mbaechler mbaechler Sep 2, 2019

Choose a reason for hiding this comment

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

do you know other timeout cause than "The timeout has been reached"?

Copy link

Choose a reason for hiding this comment

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

The server has reached it's life timeout
The user should have reach her end of life

More seriously I'm not sure it means exactly what it should (see https://tools.ietf.org/html/rfc7231#section-6.5.7 ), but I'm fine with it anyway.

Choose a reason for hiding this comment

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

can the result when reached timeout be represented in by 200 response code and a Json body telling that the task is in processing? and the message will be more clear than just a status code

Copy link
Author

Choose a reason for hiding this comment

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

A 200 status code for an exceeding timeout, I disagree, we submit a request, which is the specification of a process, we can't fulfill the requirements, we should not say that it's ok.

.orElse(Long.MAX_VALUE / 1000);

Preconditions.checkState(value > 0);
return Duration.ofSeconds(value);

Choose a reason for hiding this comment

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

Who will need to wait an HTTP request for 106751991167300 days? What if you assert a max value of 1 day for example?

.orElse(Long.MAX_VALUE / 1000);

Preconditions.checkState(value > 0);
return Duration.ofSeconds(value);

Choose a reason for hiding this comment

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

BTW, there's no test to check this "feature"

new TerminatedAwaitedTaskExecutionDetails(getExecutionDetails(id))
}
} catch {
case _: IllegalStateException => new TimeoutAwaitedTaskExecutionDetails()

Choose a reason for hiding this comment

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

do you need this _: Foo syntax ?

Copy link
Author

Choose a reason for hiding this comment

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

I think so

@rouazana
Copy link

[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR] Tests run: 6, Failures: 0, Errors: 4, Skipped: 0, Time elapsed: 1.262 s <<< FAILURE! - in org.apache.james.task.eventsourcing.MemoryTerminationSubscriberTest
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR] handlingCompletedShouldBeListed  Time elapsed: 0.225 s  <<< ERROR!
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] reactor.core.Exceptions$ReactiveException: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] Caused by: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] 
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR] handlingCancelledShouldBeListed  Time elapsed: 0.206 s  <<< ERROR!
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] reactor.core.Exceptions$ReactiveException: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] Caused by: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] 
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR] handlingMultipleEventsShouldBeListed  Time elapsed: 0.206 s  <<< ERROR!
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] reactor.core.Exceptions$ReactiveException: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] Caused by: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] 
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR] handlingFailedShouldBeListed  Time elapsed: 0.205 s  <<< ERROR!
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] reactor.core.Exceptions$ReactiveException: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] Caused by: java.lang.InterruptedException
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] 
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [INFO] Running org.apache.james.task.eventsourcing.EventSourcingTaskManagerTest
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [INFO] Tests run: 30, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 12.243 s - in org.apache.james.task.eventsourcing.EventSourcingTaskManagerTest
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [INFO] Running org.apache.james.task.SerialTaskManagerWorkerTest
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.602 s - in org.apache.james.task.SerialTaskManagerWorkerTest
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [INFO] 
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [INFO] Results:
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [INFO] 
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR] Errors: 
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR]   MemoryTerminationSubscriberTest.handlingCancelledShouldBeListed » Reactive jav...
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR]   MemoryTerminationSubscriberTest.handlingCompletedShouldBeListed » Reactive jav...
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR]   MemoryTerminationSubscriberTest.handlingFailedShouldBeListed » Reactive java.l...
[7e4f80abe2729d080169d9ba3ae7cc0fdfcb324d] [ERROR]   MemoryTerminationSubscriberTest.handlingMultipleEventsShouldBeListed » Reactive

@trantienduchn
Copy link

[e8e5929d9557e4d54330c634befa58229327cc5d] 2 errors>
[e8e5929d9557e4d54330c634befa58229327cc5d] to be an instance of:
[e8e5929d9557e4d54330c634befa58229327cc5d]   <org.apache.james.StartUpChecksPerformer.StartUpChecksException>
[e8e5929d9557e4d54330c634befa58229327cc5d] but was:
[e8e5929d9557e4d54330c634befa58229327cc5d]   <"com.google.inject.CreationException: Unable to create injector, see the following errors:
[e8e5929d9557e4d54330c634befa58229327cc5d] 
[e8e5929d9557e4d54330c634befa58229327cc5d] 1) No implementation for org.apache.james.task.eventsourcing.TerminationSubscriber was bound.
[e8e5929d9557e4d54330c634befa58229327cc5d]   Did you mean?
[e8e5929d9557e4d54330c634befa58229327cc5d]     org.apache.james.task.eventsourcing.TerminationSubscriber bound  at org.apache.james.modules.server.TaskManagerModule.configure(TaskManagerModule.java:37) (via modules: com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$OverrideModule -> com.google.inject.util.Modules$CombinedModule -> com.google.inject.util.Modules$CombinedModule -> org.apache.james.modules.CommonServicesModule -> org.apache.james.modules.server.TaskManagerModule)

@ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The taskId is not found")
@ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The taskId is invalid or invalid timeout"),
@ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The taskId is not found"),
@ApiResponse(code = HttpStatus.REQUEST_TIMEOUT_408, message = "The timeout have been reached")

Choose a reason for hiding this comment

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

can the result when reached timeout be represented in by 200 response code and a Json body telling that the task is in processing? and the message will be more clear than just a status code

} else {
Flux.from(terminationSubscriber.listenEvents)
.filter{
override final def await(id: TaskId, timeout: Duration): AwaitedTaskExecutionDetails = {

Choose a reason for hiding this comment

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

don't you think Optional<Duration> could be better?

Choose a reason for hiding this comment

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

I think the submit() need to support timeout too

Copy link
Author

Choose a reason for hiding this comment

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

No, because you would not not if you had an Option.empty due to an TaskNotFound or a TimeOut.

You want it to fail if you can not submit a Task.

@blackheaven blackheaven force-pushed the JAMES-2813-await branch 2 times, most recently from d061946 to 49f6576 Compare September 3, 2019 09:06
@blackheaven
Copy link
Author

[ERROR]   CassandraMailRepositoryTest.storingAndRemovingMessagesConcurrentlyShouldLeadToConsistentResult » Execution

test this please

.get("/" + taskId.getValue() + "/await")
.then()
.statusCode(HttpStatus.BAD_REQUEST_400)
.body("message", is("Invalid timeout"));
Copy link
Member

Choose a reason for hiding this comment

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

Why? (details?)

Copy link
Author

Choose a reason for hiding this comment

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

which details?

Copy link
Member

Choose a reason for hiding this comment

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

Why is the timeout invalid? Can you add it in the returned exception detailed field?

Copy link
Author

Choose a reason for hiding this comment

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

you pass one parameter, it is invalid, what would be the gain?

});

given()
.queryParam("timeout", "2")
Copy link
Member

Choose a reason for hiding this comment

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

Can't we reduce it to 1s? 100ms? (faster tests?)

Copy link
Author

Choose a reason for hiding this comment

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

You won't gained much

Copy link
Member

Choose a reason for hiding this comment

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

1 to 2 second a test?

Copy link
Member

Choose a reason for hiding this comment

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

1 to 2 second a test?

Copy link
Author

Choose a reason for hiding this comment

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

on 3 tests, we will survive

@Test
void getAwaitWithANonExistingTaskShouldReturnNotFound() {
when()
.get("/" + TaskId.generateTaskId().asString() + "/await")
Copy link
Member

Choose a reason for hiding this comment

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

Extract that variable to unknownTaskId?

Copy link
Author

Choose a reason for hiding this comment

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

cosmetic, I'll fix it if I have other modifications

Choose a reason for hiding this comment

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

not cosmetic IMO

try {
byte[] payload = serializer.serialize(event).getBytes(StandardCharsets.UTF_8);
AMQP.BasicProperties basicProperties = new AMQP.BasicProperties.Builder().build();
OutboundMessage message = new OutboundMessage(EXCHANGE_NAME, ROUTING_KEY, basicProperties, payload);
Copy link
Member

Choose a reason for hiding this comment

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

I see that Event => OutboundMessage serialization a bit everywhere. Wouldn't it make sens to factorize it?

Copy link
Author

Choose a reason for hiding this comment

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

Not really, we have multiple ways to serialize them

.share();
}

private Mono<Event> toEvent(Delivery delivery) {
Copy link
Member

Choose a reason for hiding this comment

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

Idem for that Delivery => Event.

}

public TaskExecutionDetails unwrap() {
throw new RuntimeException("await has failed due to timeout");
Copy link
Member

Choose a reason for hiding this comment

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

Can't we use a more specific exception?

Copy link
Author

Choose a reason for hiding this comment

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

no, it's a call issue, it's not supposed to happen in production

}

public TaskExecutionDetails unwrap() {
throw new RuntimeException("await has failed due to unknown task");
Copy link
Member

Choose a reason for hiding this comment

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

Can we use a more specific exception?

Copy link
Author

Choose a reason for hiding this comment

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

idem

@@ -58,6 +60,62 @@ public boolean isFinished() {
}
}

interface AwaitedTaskExecutionDetails {
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this a disguised sketchy staged builder?

Copy link
Author

Choose a reason for hiding this comment

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

A staged builder of one element? it will only make it heavier for no benefit

Copy link
Member

Choose a reason for hiding this comment

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

Well I have the impression that you return several time invalid variations of the same entity, for which calling unwrap fails with a not specific exception.

You require IMO too much knowledge from the caller (if I use it, I will break it) and I fail to understand the way this "thing" - that do not follow patterns that I know - work.

Can we try to review and rediscuss code organization here?

Copy link
Author

Choose a reason for hiding this comment

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

No, and I won't fix it.

  1. You'll loose in expressiveness (have a look in at tests)
  2. You'll add burden to code which is already complex adding no value
  3. You have to test the code you produce (including using this one), so you'll be corrected quickly
  4. It's perfectly acceptable to have code not behaving the way we are use to, that does not make it a bad code (rephrasing: it's not because we know things that work, that there is nothing we do not know that work too)


assertThatCode(() -> result
.onTimeout(CustomTimeoutException::new)
.onUnknown(CustomUnknownException::new)
Copy link
Member

Choose a reason for hiding this comment

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

Why is it the responsability of the caller to instanciate the exceptions?

Why can't we have well defined exceptions thrown directly by the await method?

Sorry I don't get the benefits behind all of this complexity...

Copy link
Author

Choose a reason for hiding this comment

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

Why is it the responsability of the caller to instanciate the exceptions?

I do now instantiate it here, I pass the method reference

Why can't we have well defined exceptions thrown directly by the await method?

Because reaching a timeout is not a real exception, consequently, it should not be manage like that

Sorry I don't get the benefits behind all of this complexity...

ADT are not complex, RunTimeExceptions are

Copy link
Member

Choose a reason for hiding this comment

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

I do now instantiate it here, I pass the method reference

Thanks I understand

Because reaching a timeout is not a real exception, consequently, it should not be manage like that

Thanks that's a beginning of answer

ADT are not complex, RunTimeExceptions are

Who said that it should be runtime?

Copy link
Author

Choose a reason for hiding this comment

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

Who said that it should be runtime?

Well, if it's not passed as a value, the only other non too-dirty way I see is an Exception

Copy link
Member

Choose a reason for hiding this comment

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

That would be more straightforward, no?

@@ -223,7 +225,7 @@ void getAwaitWithInvalidTimeoutShouldReturnAnError() {
.get("/" + taskId.getValue() + "/await")
.then()
.statusCode(HttpStatus.BAD_REQUEST_400)
.body("message", is("Invalid timeout"));
.body("message", allOf(containsString("Invalid timeout"), containsString("Timeout should not be positive")));
Copy link
Member

Choose a reason for hiding this comment

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

Wait... Shouldn't it be Timeout should be positive

Copy link
Member

@chibenwa chibenwa left a comment

Choose a reason for hiding this comment

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

Once the typo in the webadmin error message is fixed

@blackheaven
Copy link
Author

[272c72e69ea0fc5655cb47d64c427c5b5b8e130d] Expected: '\* SEARCH 1 2 3 4'
[272c72e69ea0fc5655cb47d64c427c5b5b8e130d] Actual   : '* SEARCH'

test this please

@@ -196,7 +196,7 @@ private Duration getTimeout(Request req) {
.filter(parameter -> !parameter.isEmpty());

requestTimeout.ifPresent(timeout ->
Preconditions.checkState(!timeout.replaceAll(" ", "").startsWith("-"), "Timeout should not be positive"));
Preconditions.checkState(!timeout.replaceAll(" ", "").startsWith("-"), "Timeout should be positive"));
Copy link
Member

Choose a reason for hiding this comment

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

Checking the first character is a strange way of ensuring a number is negative...

(Sorry, I missed it so far)

Copy link
Author

Choose a reason for hiding this comment

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

It's the only way I've founded to check it, since an Integer.parseXXX would not recognize the unit and duration parsing won't recognize the minus sign, throwing a generic error

Copy link
Member

Choose a reason for hiding this comment

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

Let me have a look...

Copy link
Member

Choose a reason for hiding this comment

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

See 2f10137

Copy link
Author

Choose a reason for hiding this comment

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

Thank you

.map(rawString -> DurationParser.parse(rawString, ChronoUnit.SECONDS))
.orElse(MAXIMUM_AWAIT_TIMEOUT);

Preconditions.checkState(timeout.compareTo(MAXIMUM_AWAIT_TIMEOUT) <= 0, "Timeout should not exceed one year");
Copy link
Member

Choose a reason for hiding this comment

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

A precondition at the end of a method look weird. Moving it to a ensureXxx method would solve this.

Copy link
Author

Choose a reason for hiding this comment

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

I did not find an example, can you give me one please?

Copy link
Member

Choose a reason for hiding this comment

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

See See 2f10137

Copy link
Author

Choose a reason for hiding this comment

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

Thank you

@chibenwa
Copy link
Member

chibenwa commented Sep 5, 2019

Overwise 👍

@Arsnael
Copy link
Member

Arsnael commented Sep 6, 2019

tests were 🍏

[272c72e69ea0fc5655cb47d64c427c5b5b8e130d] ADD failed: stat /var/lib/docker/tmp/docker-builder652555734/destination/james-server-app-3.4.0-SNAPSHOT-app.zip: no such file or directory

test this please

@blackheaven
Copy link
Author

test this please

1 similar comment
@chibenwa
Copy link
Member

chibenwa commented Sep 9, 2019

test this please

@blackheaven
Copy link
Author

test this please

}

private void assertDoesNotExceedMaximumTimeout(Duration timeout) {
Preconditions.checkState(timeout.compareTo(MAXIMUM_AWAIT_TIMEOUT) <= 0, "Timeout should not exceed one year");

Choose a reason for hiding this comment

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

s/one year/365 days/

@@ -58,6 +59,9 @@ public boolean isFinished() {
}
}

class ReachedTimeoutException extends Exception {

Choose a reason for hiding this comment

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

why the hell a checked Exception?

Copy link
Author

Choose a reason for hiding this comment

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

to force handling it

Choose a reason for hiding this comment

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

usually we use a RuntimeException for these cases, and explicitly state that the method is throwing it with a throws MyRuntimeException. What's the point here to force all the callers to handle it?

Copy link
Author

Choose a reason for hiding this comment

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

We forgot to handle it at the right places, it would be a shame to allow this kind of bug to happen again. It's a design fix.

@Arsnael
Copy link
Member

Arsnael commented Sep 10, 2019

[36d74dde41ae70ebd83f98858c6307582fe1d56a] [ERROR] Failures: 
[36d74dde41ae70ebd83f98858c6307582fe1d56a] [ERROR]   DelayTest.stringConstructorShouldThrowOnNegativeNumbers 
[36d74dde41ae70ebd83f98858c6307582fe1d56a] Expected: an instance of java.lang.NumberFormatException
[36d74dde41ae70ebd83f98858c6307582fe1d56a]      but: <java.lang.IllegalArgumentException: Duration amount should be positive> is a java.lang.IllegalArgumentException

@blackheaven
Copy link
Author

ADD failed: stat /var/lib/docker/tmp/docker-builder143880794/destination/james-server-app-3.4.0-SNAPSHOT-app.zip: no such file or directory

can be considered 🍏

@Arsnael
Copy link
Member

Arsnael commented Sep 13, 2019

CassandraMailRepositoryTest.storingAndRemovingMessagesConcurrentlyShouldLeadToConsistentResult » Execution

test this please

@remk
Copy link
Member

remk commented Sep 18, 2019

test this please

}

@Test
default void awaitShouldAwaitWaitingTask() {
default void awaitShouldAwaitWaitingTask() throws TaskManager.ReachedTimeoutException, InterruptedException {

Choose a reason for hiding this comment

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

throws Exception is sufficient for a test

@@ -58,6 +59,9 @@ public boolean isFinished() {
}
}

class ReachedTimeoutException extends Exception {

Choose a reason for hiding this comment

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

usually we use a RuntimeException for these cases, and explicitly state that the method is throwing it with a throws MyRuntimeException. What's the point here to force all the callers to handle it?

@chibenwa chibenwa added the waiting_merge We are about to merge this! label Sep 24, 2019
@chibenwa
Copy link
Member

Merged

@chibenwa chibenwa closed this Sep 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting_merge We are about to merge this!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants