-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
TRUNK-4253:Made PatientService.savePatient threadsafe #2615
Conversation
t1.start(); | ||
t2.start(); | ||
|
||
assertTrue(isSavePatientThreadsafe.get()); |
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.
You should check for assertFalse
since the default value is set to false
.
@@ -1848,6 +1853,48 @@ public void savePatient_shouldUpdateAnExistingPatient() throws Exception { | |||
assertTrue("The gender should be new", patient2.getGender().equals("F")); | |||
} | |||
|
|||
@Test | |||
public void savePatient_shouldFailSaveIfPatientsWithSameIdentifierAreSaved() { | |||
isSavePatientThreadsafe = new AtomicBoolean(false); |
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.
Just one opinion,
isSavePatientThreadsafe
would be changed to true
by default or isSavePatientThreadUnSafe = false
by default will good for the naming. Because at the beginning all threads are in safe state and it will become the critical stage while you are performing the saving method.
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.
@samuelmale did you see the above?
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.
@samuelmale did you see the above?
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.
Cool, I have just seen its significancy @dkayiwa
I'm sorry
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.
Cool, I have just seen its significancy @dkayiwa
I'm sorry
@samuelmale does the unit test fail when you remove the changes in PatientServiceImpl? |
Yes. The test fails @dkayiwa |
@@ -1881,7 +1934,7 @@ public void getAllPatients_shouldFetchVoidedPatientsWhenGivenIncludeVoidedIsTrue | |||
List<Patient> allPatients = patientService.getAllPatients(true); | |||
// there are 1 voided and 4 nonvoided patients in | |||
// standardTestDataset.xml | |||
assertEquals(6, allPatients.size()); | |||
assertEquals(7, allPatients.size()); |
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.
Why is this necessary?
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.
Hi,
I have been facing this challenge for a while. Its all about Threads saving the data to the "in-memory-database" and effects aren't reverted as the default behavior is to other tests. Could I be missing something when using Threads?
The above happens because of this line. Meaning the patient is saved the effect ain't reverted hence I had to change the number of patients from 6 to 7. Its exactly the same issue in this thread. Could you please advise me on this?
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.
All I know is that changes in one thread aren't visible in others in tests since the transactions get rollback.
What I don't understand is why it's happening now and not before because the test was passing before your changes
@wluyima I have added some changes |
|
||
try { | ||
t1.join(); | ||
//t2.join(); |
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.
Did you take a look at this? https://wiki.openmrs.org/display/docs/Java+Conventions#JavaConventions-Donotcommentoutcode
Just removed the comment @dkayiwa |
@Override | ||
public Patient savePatient(Patient patient) throws APIException { | ||
synchronized(this) { | ||
requireAppropriatePatientModificationPrivilege(patient); |
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.
Did you intentionally decide not to TAB the code within the synchronised phrase?
} | ||
public void savePatientOnThread(UserContext ctx, Patient patient) { | ||
Context.setUserContext(ctx); | ||
Context.openSessionWithCurrentUser(); |
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 you also fix the above indention? Same with a couple of other places in your commit.
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 wonder, but locally, the indention is fine. Just to prove, hit view full file and check.
I have highlighted the it here https://github.com/samuelmale/openmrs-core/blob/fd2aed2031b647f046562da4142851669c3c4061/api/src/test/java/org/openmrs/api/PatientServiceTest.java#L1890-L1894
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.
If this is the unaddressed comment, I'm pretty sure my indention is fine. Have you looked at it as a file. In otherwise have looked at the above link? @dkayiwa
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.
If this is the unaddressed comment, I'm pretty sure my indention is fine. Have you looked at it as a file. In otherwise have looked at the above link? @dkayiwa
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.
Still your PR doesn't have the proper indentation. See here.
Sometimes it happened to me in the IDE also, but can't figure out using that same IDE at the same time. Better to open this file with another text editor(Sublime or VSCode) to check for the indentations. You can easily find out your issues.
setPreferredPatientIdentifier(patient); | ||
setPreferredPatientName(patient); | ||
setPreferredPatientAddress(patient); | ||
synchronized(this) { |
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.
Do you have a reason for using a synchronised block instead of method?
I'm of the view that we use synchronized blocks, a sync'd method makes it not thread safe @dkayiwa check the CI failure |
Can you share the link where you read that? |
I have just run 'mvn clean install' on this branch twice and it builds. I wonder whats happening with CI |
I have restarted the build |
Cool, just waiting for yr review @dkayiwa |
Could you restart the CI build once more @dkayiwa ? |
Even compiling it locally on your machine should fail too. |
Noo, it actually passes @kayiwa Daniel <danielkayiwa@gmail.com>
…On Wed, Jul 18, 2018 at 1:38 AM dkayiwa ***@***.***> wrote:
Even compiling it locally on your machine should fail too.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2615 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AY4E5bE8x5RqQKvS_iXONlPSNO8fcPn2ks5uHmdpgaJpZM4SgU34>
.
|
@samuelmale i have restarted it several times and noticed that some times it fails while other times it passed. Whenever it fails, the error message is as below: Results : |
I just run it another time and got this: Results : |
Do you mind fetching this branch and testing it out locally?
…On Wed, Jul 18, 2018, 5:19 PM dkayiwa ***@***.***> wrote:
I just run it another time and got this:
Results :
Failed tests:
PatientServiceTest.getAllPatients_shouldFetchVoidedPatientsWhenGivenIncludeVoidedIsTrue:1938
expected:<6> but was:<8>
PatientServiceTest.savePatient_shouldFailSaveIfPatientsWithSameIdentifierAreSaved:1884
IdentifierNotUniqueException not thrown, method not Threadsafe
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2615 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AY4E5cQIRUpVdQt283xYplvSS6k_mt9aks5uH0P6gaJpZM4SgU34>
.
|
But now it builds successfully @dkayiwa Could you take a second look? |
Like i said, it is random. I have just rerun it and now you can see the failure. |
So whats really going on, but locally its not random @dkayiwa |
Tru dat! |
So whats up @dkayiwa |
@samuelmale the very fact that the test randomly fails in some instances, makes me feel like it needs some more work. |
This weird behaviour started when I changed from a blocked synchronized block to a method synchronized block @dkayiwa . Do we have reasons as to why we can't use the block synchronization? |
I remember as if it still failed even with block synchronisation. Any way, you can change it back and will show you by simply running travis again. |
Hahaha okie @dkayiwa |
Whats going on here @dkayiwa . |
@samuelmale i have just rebuilt it three times. For the first two times, it succeeded. But failed on the third one. |
ahhhhh!!!! But have you ever hit upon such a case? @dkayiwa |
Ummmmm. Rarely! |
@samuelmale any more ideas on the above Travis failures? |
I think ur problem is that savePatient is not thread safe and you have no idea if ur executing inside a pre-existing transaction. Create a separate hibernate transaction/session and that should work, i also have the habit for explicitly begin/commit every transaction even if single statement. |
Ticket: https://issues.openmrs.org/browse/TRUNK-4253