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

Mongo #731

Merged
merged 35 commits into from
Jan 8, 2019
Merged

Mongo #731

merged 35 commits into from
Jan 8, 2019

Conversation

sdesmond46
Copy link
Contributor

Notice

It is not allowed to submit your PR to the master branch directly, please submit your PR to the master-pre-merge branch.

Description

This change adds support for a new database vendor - MongoDB. This will be the first database which is not stored in the file system where the kernel is running, which allows for more flexibility when deploying and running kernels.

The change introduces a runtime dependency on the Mongo Java Driver, and a test dependency on Mongo DB itself so we can test against a localhost Mongo instance.

To use the Mongo driver to connect to a Mongo database running on your local machine, you would update the config.xml with <vendor>mongodb</vendor> and <path>mongodb://localhost:27017</path>

Type of change

Insert x into the following checkboxes to confirm (eg. [x]):

  • Bug fix.
  • New feature.
  • Enhancement.
  • Unit test.
  • Breaking change (a fix or feature that causes existing functionality to not work as expected).
  • Requires documentation update.

Testing

Please describe the tests you used to validate this pull request. Provide any relevant details for test configurations as well as any instructions to reproduce these results.

  • Tested running the kernel locally with Mongo and with the existing db providers
  • Added unit tests
  • These changes are actively running on the Nodesmith service without issue

Verification

Insert x into the following checkboxes to confirm (eg. [x]):

  • I have self-reviewed my own code and conformed to the style guidelines of this project.
  • New and existing tests pass locally with my changes.
  • I have added tests for my fix or feature.
  • I have made appropriate changes to the corresponding documentation.
  • My code generates no new warnings.
  • Any dependent changes have been made.

@AionJayT
Copy link
Collaborator

@sdesmond46 Thanks for your contribution. Do you have benchmark test or data for the implementation?

@sdesmond46
Copy link
Contributor Author

@sdesmond46 Thanks for your contribution. Do you have benchmark test or data for the implementation?

I didn't do any formal benchmark testing on it, but I didn't see any real performance issues compared to one LevelDB when Mongo was running on the same machine. There is obviously a bit more latency when Mongo is running on a different machine, but it certainly wasn't something that made the kernel unusable.

I'm happy to add some more formal testing if that would help though.

@AionJayT
Copy link
Collaborator

AionJayT commented Dec 3, 2018

@sdesmond46 Thanks for your contribution. Do you have benchmark test or data for the implementation?

I didn't do any formal benchmark testing on it, but I didn't see any real performance issues compared to one LevelDB when Mongo was running on the same machine. There is obviously a bit more latency when Mongo is running on a different machine, but it certainly wasn't something that made the kernel unusable.

I'm happy to add some more formal testing if that would help though.

Thanks for your info update.

Copy link
Collaborator

@AionJayT AionJayT left a comment

Choose a reason for hiding this comment

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

Overall the PR is awesome! Thanks for your contribution.
Few things I think need to be changed before getting this PR to merge into the aion repo:

  1. Some of the logs should be put into "DEBUG" instead of all "INFO"
  2. the binary file inside the testing resource is too big, could you find a way to put the link instead of put whole binary into it? Or can it be built by source code?
  3. The Aion repo is going to switch license from GPL_V3 to MIT, are you agree your contribution be a part of the MIT license?
  4. I am getting some errors when I launch the kernel with mondb in the "custom" network, could you give me the correct settings for eliminating the following message?Thanks.

18-12-03 18:00:14.905 INFO DB [main]: Initializing MongoDB at mongodb://localhost:37017
18-12-03 18:00:14.907 INFO DB [main]: Creating new mongo client to connect to mongodb://localhost:37017
18-12-03 18:00:14.991 INFO DB [main]: Finished opening the Mongo connection
18-12-03 18:00:14.991 ERROR DB [main]: Database cannot be saved to disk for .
18-12-03 18:00:14.991 INFO DB [main]: Initializing MongoDB at mongodb://localhost:37017
18-12-03 18:00:14.991 INFO DB [main]: Reusing existing mongo client for mongodb://localhost:37017
18-12-03 18:00:14.991 INFO DB [main]: Finished opening the Mongo connection
18-12-03 18:00:14.992 ERROR DB [main]: Database cannot be saved to disk for .

@sdesmond46
Copy link
Contributor Author

@AionJayT thanks for taking a look!

Couple of responses to your questions:

  1. Good call, I bumped some of the levels down on some logs
  2. I looked into this and couldn't quite figure out an elegant solution. Is the issue that the file is too large to be included as a test resource, or the file is too large to be in the git repo? I can dig into including & building the source, but I think the Mongo repo is pretty large
  3. The license change is totally fine with me :)
  4. I noticed that error too and made a change to suppress it. It was just a place where we were checking if the file was saved to disk instead of checking that it is persisted somewhere.

@AionJayT
Copy link
Collaborator

AionJayT commented Dec 12, 2018

For point 2.
Usually, we don't put that big file into the github repo. The better way I think is writing a script to build the mongo db when the developer tries to run the mongo db test in the first time.

@@ -33,7 +33,7 @@ if [ "$noGui" != "true" ] && [ ! -d "$JAVAFX_PATH" ]; then
fi

module_path=$JDK_PATH/jmods
add_modules="java.base,java.xml,java.logging,java.management,jdk.unsupported,jdk.sctp"
add_modules="java.base,java.xml,java.logging,java.management,jdk.unsupported,jdk.sctp,java.security.sasl"
Copy link
Contributor

Choose a reason for hiding this comment

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

@aion-kelvin I think this change will impact the GUI PR. Just making a note here to not lose track of the change.

Copy link
Contributor

@AlexandraRoatis AlexandraRoatis left a comment

Choose a reason for hiding this comment

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

LGTM. Thank you for the contribution! Approved pending @AionJayT's approval.

Copy link
Contributor

@aion-kelvin aion-kelvin left a comment

Choose a reason for hiding this comment

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

Hey @sdesmond46, thank you for your work on this. Overall it looks pretty good. I have a suggestion for your connection manager class. Also, I like the shell script for starting up a MongoDb via Docker. I was thinking -- would it make more sense to have the shell script install MongoDb from Docker Hub, instead of checking in a Docker binary into Github?

* class keeps track of reference counting active instances and will close the connection once all instances
* are done being used.
*/
public class MongoConnectionManager {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this class meant to be thread-safe? I presumed yes due to the ConcurrentHashMap.

If yes, I think getMongoClientInstance and closeMongoClientInstance need to be marked synchronized. For instance, it would be a problem if two threads call closeMongoClientInstance("myURL") around the same time when activeClientCount of "myURL" is 1, then the following sequence can happen:

  • thread 1 runs the first if check and doesn't enter the exception entering code
  • thread 2 runs the first if check and doesn't enter the exception entering code
  • thread 1 completes the rest of the method, which means it executes the mongoUriToClientMap.remove(mongoClientUri) in the second if-block
  • thread 2 then continues and throws NullPointerException on this.activeClientCountMap.get(mongoClientUri).decrementAndGet() because thread 1 already removed it

I believe getMongoClientInstance has a similar issue with its "check if in map; otherwise put in map" logic

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah you're totally right, it is meant to be thread safe but I forgot the synchronized keyword. I'll add that in, thanks for catching it.

@sdesmond46
Copy link
Contributor Author

sdesmond46 commented Dec 14, 2018

@aion-kelvin - Re: using Docker and the Mongo binaries -- The script I added runs mongo with the docker image available on DockerHub, docker run will pull the Docker image from Docker Hub if it doesn't exist on the local machine. I used docker for local testing since it cleans its self up easier and works no matter what OS I'm using.

The mongod and mongo binaries are added are only used in the unit tests, since I didn't think it would be ok to require Docker to be installed on running to have the tests pass. @AionJayT would it be reasonable to require Docker for the tests? Then we wouldn't need to check in the binaries I did -- when the tests ran the docker image would just get pulled from docker hub if it didn't exist on the local machine. I'll also look into adding a script to build mongo from source in the meantime.


Update: I looked into building mongo from source, but that doesn't seem like a great option because their source is ~220MB and it's still not done building after an hour on my machine which doesn't seem acceptable. The other option which could work is to download the Mongo tarball from https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1404-3.6.9.tgz, extract that and use that in the tests. That file is about 100MB

@aion-kelvin
Copy link
Contributor

Thanks for the changes! Code looks good to me -- once we figure out how to package the mongo binary I think we're good to go.

The mongod and mongo binaries are added are only used in the unit tests, since I didn't think it would be ok to require Docker to be installed on running to have the tests pass. @AionJayT would it be reasonable to require Docker for the tests? Then we wouldn't need to check in the binaries I did -- when the tests ran the docker image would just get pulled from docker hub if it didn't exist on the local machine. I'll also look into adding a script to build mongo from source in the meantime.

I'll defer to @AionJayT for the final decision, but IMO if the test needs to call an external program, it is an integration test, not a unit test. And I think it is ok for an integration test to need extra set-up.

@AionJayT
Copy link
Collaborator

AionJayT commented Dec 17, 2018

@sdesmond46 I total agree with using docker for testing the mongo. Could you able to do this change?

Samm Desmond added 2 commits December 18, 2018 16:12
This changes switches to use docker instead of running the raw mongo binary when executing the mongo driver tests. It uses Spotify's Docker controller library to interact with the docker service
@sdesmond46
Copy link
Contributor Author

@sdesmond46 I total agree with using docker for testing the mongo. Could you able to do this change?

Yep, I just made the changes. They assume that there is a running docker daemon on the machine, and exec and cleanup the mongo container, but remove the mongo binaries from the repo

@AionJayT
Copy link
Collaborator

@sdesmond46 the ciBuild has tailed tests, could you able to fix it?
org.aion.db.impl.AccessWithExceptionTest > initializationError FAILED
java.lang.RuntimeException
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.AssertionError at AccessWithExceptionTest.java:86

org.aion.db.impl.DriverBaseTest > initializationError FAILED
java.lang.NoClassDefFoundError at DriverBaseTest.java:307

org.aion.db.impl.ConcurrencyTest > initializationError FAILED
java.lang.RuntimeException
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.NoClassDefFoundError at ConcurrencyTest.java:90

@sdesmond46
Copy link
Contributor Author

@sdesmond46 the ciBuild has tailed tests, could you able to fix it?
org.aion.db.impl.AccessWithExceptionTest > initializationError FAILED
java.lang.RuntimeException
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.AssertionError at AccessWithExceptionTest.java:86

org.aion.db.impl.DriverBaseTest > initializationError FAILED
java.lang.NoClassDefFoundError at DriverBaseTest.java:307

org.aion.db.impl.ConcurrencyTest > initializationError FAILED
java.lang.RuntimeException
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.NoClassDefFoundError at ConcurrencyTest.java:90

Yeah .I spent some time digging it this and trying to figure out a solution,. The root cause is the tests can't connect to a running Docker service to start up the mongo container when running in the CI environment. I'm not super familiar with Jenkins and the way the runners are set up for Aion, so I wasn't sure if that's because there isn't a docker service running, or I don't know the right DOCKER_HOST to connect to it. Is there any info on how the Jenkins agents are configured for the Aion CI environment? Thanks for the help!

@AionJayT
Copy link
Collaborator

AionJayT commented Jan 8, 2019

merge this PR in and will try (or ignore) to fix the fail tests.

@AionJayT AionJayT merged commit d562a24 into aionnetwork:master-pre-merge Jan 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants