Skip to content

Conversation

@Artem-Semenov-dev
Copy link
Contributor

This PR implements the SharePriceMovement projection, which allows us to observe the price movement of a particular share over a one-minute period. This projection will be used to draw the share price charts on the corresponding page of the application.

@Artem-Semenov-dev Artem-Semenov-dev self-assigned this Jul 17, 2023
Copy link
Contributor

@armiol armiol left a comment

Choose a reason for hiding this comment

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

@Artem-Semenov-dev please see my comments. We are getting really close, but still I believe we should simplify internal things.

}
}

private S onceUpdated() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's document this method as well.

I think it is now called waitForUpdate().

future.complete(value);
}

private S state() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure why this method still waits for something. What is the expected scenario? Maybe it should return @Nullable state instead?

I also don't understand why clearState() still exists, instead of instantiating future field each time when we need this "waiting" for the result.

I think, state() also deserves some documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I still believe that we need to clear the state of the entity before we send a command to the server. I think that the client observer on the entity state is triggered immediately (or after a very little amount of time) after we send a command, so if we gonna clear the state of the entity after sending a command, it will reinitialize the future which has been already triggered by the command.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Artem-Semenov-dev the thing here is that clearState() does not clear the state of the entity.

I would think that we should remember the last update of S value, and return it here. While all the gymnastics with futures should stay in setState and waitForUpdate.

Let's discuss this vocally.

@Artem-Semenov-dev Artem-Semenov-dev requested a review from armiol July 19, 2023 09:46
Copy link
Contributor

@armiol armiol left a comment

Choose a reason for hiding this comment

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

@Artem-Semenov-dev please see my comments.

import io.spine.base.EntityState;
import io.spine.client.Client;
import io.spine.core.UserId;
import org.jetbrains.annotations.Nullable;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use a proper annotation.

It should look like this:

import org.checkerframework.checker.nullness.qual.Nullable;

...

public @Nullable TenantId tenantId() {
       return tenantId;
}

future.complete(value);
}

private S state() {
Copy link
Contributor

Choose a reason for hiding this comment

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

@Artem-Semenov-dev the thing here is that clearState() does not clear the state of the entity.

I would think that we should remember the last update of S value, and return it here. While all the gymnastics with futures should stay in setState and waitForUpdate.

Let's discuss this vocally.

@Artem-Semenov-dev Artem-Semenov-dev requested a review from armiol July 24, 2023 15:57
Copy link
Contributor

@armiol armiol left a comment

Choose a reason for hiding this comment

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

Please see my comments.

.getShareList();
return shares;
var marketShares = availableMarketShares.state();
Preconditions.checkNotNull(marketShares);
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be imported statically.

And also, that should probably be requireNonNull, which is a part of JDK.

Same below.

throw illegalStateWithCauseOf(e);
}
}
super(consumer -> client.onBehalfOf(user)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to extract these lambda expressions to methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not possible. We can access the methods before the supertype constructor call only if they are static, but we have a generic type S. So in our case, we cannot extract these lambdas to methods.

/**
* Observer for entity state changes.
*
* <p>It allows to observe the asynchronous mutations of the entity state.
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's start with "Allows".

* <p>It allows to observe the asynchronous mutations of the entity state.
*
* @param <S>
* the state to observe.
Copy link
Contributor

Choose a reason for hiding this comment

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

In Java, we don't put periods at the end of parameter descriptions.


private CompletableFuture<S> future = new CompletableFuture<>();

private S state = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

In which case, the field is @Nullable.

Same below.

* and these states were introduced to restrict the order of the observing operations.
*/
private enum ObservationState {
OBSERVED,
Copy link
Contributor

Choose a reason for hiding this comment

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

This name is confusing. Can you please document each enum member, so that I could come up with alternative name?

Please think about this one too.

future = new CompletableFuture<>();
}
try {
S updatedEntity = future.whenComplete((value, error) -> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's reduce code nesting.

Maybe, extract some bits?

/**
* Represents the states of the entity observation.
*
* <p>The `AsyncObserver` can observe asynchronous changes of the entity's state,
Copy link
Contributor

Choose a reason for hiding this comment

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

Use @code in Javadoc.

import static java.time.Duration.ofSeconds;
import static org.junit.jupiter.api.Assertions.assertThrows;

@DisplayName("'AsyncObserver' should")
Copy link
Contributor

Choose a reason for hiding this comment

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

We usually use back-ticks in display names. Yes, I know it looks funny along with my previous comment.


public AsyncStateMutator(String state, Duration delay) {
this.state.set(state);
mutationNotifier = consumer ->
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's reduce code nesting.

@Artem-Semenov-dev Artem-Semenov-dev requested a review from armiol July 25, 2023 10:12
Copy link
Contributor

@armiol armiol left a comment

Choose a reason for hiding this comment

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

@Artem-Semenov-dev I appreciate the movement towards addressing previous concerns and comments. And it looks much better now. However, as discussed separately, we should do a bit more.

  1. Shorten the implementation of EntitySubscription's ctor, as discussed via chat.
  2. Get rid of Consumer<Consumer<S>> by
    a. definitely extracting, naming and documenting the inner part (Consumer<S>),
    b. and most likely, extracting the outer Consumer<whatever the one above is going to be called> into something meaningful.

This is for sure. I will continue reviewing the rest of the changes, once these comments are addressed.

@Artem-Semenov-dev Artem-Semenov-dev requested a review from armiol July 26, 2023 09:13
@armiol armiol removed their request for review August 2, 2023 12:35
@armiol armiol assigned armiol and unassigned Artem-Semenov-dev Aug 2, 2023
@armiol
Copy link
Contributor

armiol commented Aug 2, 2023

@Artem-Semenov-dev once again, I am reassigning this PR to myself now. Will pick it up once I get a chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants