-
Notifications
You must be signed in to change notification settings - Fork 12
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
Fix how the Migration
s with custom state update are applied
#1298
Conversation
Also, refactor the code so the entity changes are transaction-based and propagated to the entity on transaction commit, instead of being applied in-place. This should make the migration logic as well as the values observed when debugging clearer.
…into fix-migrations
Removing this workaround leads to heavily verbose setup for some of the test cases, to the point where it makes it harder to understand the original meaning of the test. To address the problem, the concept of having `repository.create(ID)` which returns an invalid entity, which then cannot be loaded, should be revisited as a whole.
Codecov Report
@@ Coverage Diff @@
## master #1298 +/- ##
============================================
+ Coverage 91.04% 91.08% +0.04%
- Complexity 4745 4747 +2
============================================
Files 608 608
Lines 15088 15091 +3
Branches 854 854
============================================
+ Hits 13737 13746 +9
+ Misses 1083 1080 -3
+ Partials 268 265 -3 |
@armiol, @yuri-sergiichuk PTAL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmitrykuzmin PTAL at the comments below.
@@ -238,6 +239,7 @@ private void warnOnNoSystemEventsPosted() { | |||
private boolean physicallyRemoveRecord; | |||
|
|||
private final E entity; | |||
private @MonotonicNonNull Transaction<I, E, S, ?> tx; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please reorder fields so that final
s are grouped together?
Also, it looks like the tx
should be marked as @LazyInit
as well, right?
server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryTest.java
Show resolved
Hide resolved
assertThat(entityWithColumns.state() | ||
.getIdString()).isEqualTo(id.toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd actually compare state
and not the ID only.
server/src/test/java/io/spine/server/projection/given/SetTestProjectionName.java
Outdated
Show resolved
Hide resolved
server/src/test/java/io/spine/server/procman/given/repo/SetTestProcessName.java
Outdated
Show resolved
Hide resolved
public final class SetTestProcessName | ||
extends ProcessManagerMigration<ProjectId, TestProcessManager, Project, Project.Builder> { | ||
|
||
public static final String NEW_NAME = "Migrated project"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe Migrated process
? You have Migrated projection
in the projection migration below.
@@ -738,7 +815,8 @@ void deleteEntityViaMigration() { | |||
|
|||
Optional<TestProcessManager> found = repository().find(id); | |||
assertThat(found.isPresent()).isTrue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a whole set of Truth8
assertions that should allow having a bit nicer syntax for Optional
s. Could you please check it out and consider using them instead?
@@ -238,6 +239,7 @@ private void warnOnNoSystemEventsPosted() { | |||
private boolean physicallyRemoveRecord; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the Operation
docs it states that it's the operation done on an entity instance. In fact, we apply the migration to the tx().builder()
now, right?
I guess it really worth adding some more details on how the migration operation is actually being done while you're in the context now.
…SetTestProjectionName.java Co-authored-by: Yuri Sergiichuk <23313616+yuri-sergiichuk@users.noreply.github.com>
…o/SetTestProcessName.java Co-authored-by: Yuri Sergiichuk <23313616+yuri-sergiichuk@users.noreply.github.com>
…into fix-migrations
@yuri-sergiichuk PTAL again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmitrykuzmin PTAL at the comments.
* <p>The operation is performed in scope of an active {@link Transaction}. | ||
* | ||
* <p>All entity state and meta-data changes are propagated to the transaction and remain in | ||
* pending state until a transaction {@linkplain Transaction#commit() commit} which is the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it should be either a transaction is committed
or a transaction commit is called
* {@linkplain Operation operation}. | ||
* Applies the migration {@linkplain Operation operation} to a given entity. | ||
* | ||
* @see Operation Migration.Operation for details |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This see
section looks redundant. You have the very same link as for operation
. I'd better remove it.
@@ -71,15 +72,15 @@ void passNullToleranceCheck() { | |||
void letPass() { | |||
BusFilter<CommandEnvelope> filter = new BusFilters.Accepting(); | |||
Optional<Ack> ack = filter.filter(commandEnvelope); | |||
assertThat(ack.isPresent()).isFalse(); | |||
Truth8.assertThat(ack).isEmpty(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please import assertThat
statically here and in the other places.
@@ -675,7 +754,8 @@ void updateColumns() { | |||
|
|||
// Check the column value is propagated to the entity state. | |||
TestProcessManager entityWithColumns = afterMigration.next(); | |||
assertThat(entityWithColumns.state().getIdString()).isEqualTo(id.toString()); | |||
assertThat(entityWithColumns.state() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please have expected state here as well?
@@ -723,8 +803,9 @@ void archiveEntityViaMigration() { | |||
repository().applyMigration(id, new MarkPmArchived<>()); | |||
|
|||
Optional<TestProcessManager> found = repository().find(id); | |||
assertThat(found.isPresent()).isTrue(); | |||
assertThat(found.get().isArchived()).isTrue(); | |||
Truth8.assertThat(found).isPresent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use static imports.
@@ -773,6 +855,7 @@ private static TargetFilters targetFilters(QueryFilter first, QueryFilter... res | |||
} | |||
|
|||
private static boolean hasId(TestProcessManager projection, ProjectId id) { | |||
return projection.id().equals(id); | |||
return projection.id() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's flip the params. You'll then be able to have them on the same line.
assertThat(results) | ||
.comparingElementsUsing(idCorrespondence()) | ||
.containsExactly(id1, id2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we test states here as well?
@@ -623,7 +699,7 @@ void archiveEntityViaMigration() { | |||
repository().applyMigration(id, new MarkProjectionArchived<>()); | |||
|
|||
Optional<TestProjection> found = repository().find(id); | |||
assertThat(found.isPresent()).isTrue(); | |||
Truth8.assertThat(found).isPresent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use static imports.
…java Co-authored-by: Yuri Sergiichuk <23313616+yuri-sergiichuk@users.noreply.github.com>
# Conflicts: # server/src/main/java/io/spine/server/entity/Migration.java
@yuri-sergiichuk PTAL again. |
assertThat(results).hasSize(2); | ||
assertThat(results) | ||
.comparingElementsUsing(stateWithPropagatedName()) | ||
.containsExactly(pm1, pm2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the migration does nothing? We're comparing the results to the same PMs we've manually stored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, now I see that inside the correspondence we actually manually change the state of the PMs to match the actual one. It looks a bit too complicated...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmitrykuzmin in general LGTM.
I'd prefer to have a bit more straight-forward states comparison.
This PR fixes #1297.
The root cause of the bug is a discrepancy between entity and underlying transaction versions in
Migration
when updating the entity state.This PR thus adds the missing
setVersion(...)
call.It also applies some refactoring to the
Migration
class. Its current logic is confusing, with entity updates being propagated partially in-place, partially on transaction commit. This leads to strange code paths and observed values when debugging.After the refactoring, all entity changes will be propagated on transaction commit at the very end of
Migration.applyTo(...)
.