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

TRUNK-4253:Made PatientService.savePatient threadsafe #2615

Closed
wants to merge 1 commit into from

Conversation

samuelmale
Copy link
Member

t1.start();
t2.start();

assertTrue(isSavePatientThreadsafe.get());
Copy link
Member

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);
Copy link
Member

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.

Copy link
Member

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?

Copy link
Member

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?

Copy link
Member Author

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

Copy link
Member Author

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

@coveralls
Copy link

coveralls commented Mar 7, 2018

Coverage Status

Coverage increased (+0.04%) to 59.119% when pulling aca88d8 on samuelmale:TRUNK-4253 into 33f2195 on openmrs:master.

@dkayiwa
Copy link
Member

dkayiwa commented Mar 27, 2018

@samuelmale does the unit test fail when you remove the changes in PatientServiceImpl?

@samuelmale
Copy link
Member Author

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());
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 this necessary?

Copy link
Member Author

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?

@dkayiwa also asked me about it here.

Copy link
Member

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

@samuelmale
Copy link
Member Author

@wluyima I have added some changes


try {
t1.join();
//t2.join();
Copy link
Member

Choose a reason for hiding this comment

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

@samuelmale
Copy link
Member Author

Just removed the comment @dkayiwa

@Override
public Patient savePatient(Patient patient) throws APIException {
synchronized(this) {
requireAppropriatePatientModificationPrivilege(patient);
Copy link
Member

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();
Copy link
Member

@dkayiwa dkayiwa Jul 13, 2018

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.

Copy link
Member Author

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

Copy link
Member Author

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

Copy link
Member Author

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

Copy link
Member

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) {
Copy link
Member

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?

@samuelmale
Copy link
Member Author

I'm of the view that we use synchronized blocks, a sync'd method makes it not thread safe @dkayiwa

check the CI failure

@dkayiwa
Copy link
Member

dkayiwa commented Jul 16, 2018

Can you share the link where you read that?

@samuelmale
Copy link
Member Author

I have just run 'mvn clean install' on this branch twice and it builds. I wonder whats happening with CI

@dkayiwa

@dkayiwa
Copy link
Member

dkayiwa commented Jul 17, 2018

I have restarted the build

@samuelmale
Copy link
Member Author

Cool, just waiting for yr review @dkayiwa

@samuelmale
Copy link
Member Author

Could you restart the CI build once more @dkayiwa ?

@dkayiwa
Copy link
Member

dkayiwa commented Jul 17, 2018

Even compiling it locally on your machine should fail too.

@samuelmale
Copy link
Member Author

samuelmale commented Jul 17, 2018 via email

@dkayiwa
Copy link
Member

dkayiwa commented Jul 18, 2018

@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 :
Failed tests:
PatientServiceTest.getAllPatients_shouldFetchVoidedPatientsWhenGivenIncludeVoidedIsTrue:1938 expected:<6> but was:<7>
PatientServiceTest.savePatient_shouldFailSaveIfPatientsWithSameIdentifierAreSaved:1884 IdentifierNotUniqueException not thrown, method not Threadsafe
Tests run: 4022, Failures: 2, Errors: 0, Skipped: 36

@dkayiwa
Copy link
Member

dkayiwa commented Jul 18, 2018

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
Tests run: 4022, Failures: 2, Errors: 0, Skipped: 36

@samuelmale
Copy link
Member Author

samuelmale commented Jul 18, 2018 via email

@samuelmale
Copy link
Member Author

But now it builds successfully @dkayiwa

Could you take a second look?

@dkayiwa
Copy link
Member

dkayiwa commented Jul 18, 2018

Like i said, it is random. I have just rerun it and now you can see the failure.

@samuelmale
Copy link
Member Author

So whats really going on, but locally its not random @dkayiwa

@dkayiwa
Copy link
Member

dkayiwa commented Jul 18, 2018

Tru dat!
Looks like it depends on the computer processing power.

@samuelmale
Copy link
Member Author

So whats up @dkayiwa

@dkayiwa
Copy link
Member

dkayiwa commented Jul 22, 2018

@samuelmale the very fact that the test randomly fails in some instances, makes me feel like it needs some more work.

@samuelmale
Copy link
Member Author

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?

@dkayiwa
Copy link
Member

dkayiwa commented Jul 23, 2018

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.

@samuelmale
Copy link
Member Author

Hahaha okie @dkayiwa

@samuelmale
Copy link
Member Author

Whats going on here @dkayiwa .
I has failed again. Could you restart travis?

@dkayiwa
Copy link
Member

dkayiwa commented Jul 23, 2018

@samuelmale i have just rebuilt it three times. For the first two times, it succeeded. But failed on the third one.

@samuelmale
Copy link
Member Author

ahhhhh!!!! But have you ever hit upon such a case? @dkayiwa

@dkayiwa
Copy link
Member

dkayiwa commented Jul 23, 2018

Ummmmm. Rarely!

@suthagar23
Copy link
Member

@samuelmale any more ideas on the above Travis failures?

@samuelmale samuelmale closed this Sep 6, 2018
@bejelith
Copy link

bejelith commented Nov 3, 2021

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.

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.

6 participants