Google Code-In wrap up: Parker Erway & OpenMRS

I’m Parker Erway. I’ve been working with OpenMRS for the last couple months as part of Google Code-in 2014, a contest with the intent of encouraging kids ages 13-17 to contribute to open source organizations. I’d say it’s working!

OpenMRS itself has a wonderful mission statement:

The mission of OpenMRS is to improve health care delivery in resource-constrained environments by coordinating a global community that creates a robust, scalable, user-driven, open source medical record system platform.

I’ve had fun and learned a great deal contributing to OpenMRS. This is a summary of my work with OpenMRS:

Tasks Completed:

  •  Develop an iOS client for OpenMRS. I love working with Apple technologies, they almost always simply work. This task, and it’s accompanying tasks (adding more features to the app, documenting it, and publishing it on the App Store) took nearly three weeks.I could have done them faster, but I wanted to incorporate every best practice I knew of. One of my favorite things to do is start a fresh new project and try to do everything perfectly. It was great seeing all that hard work (and learning!) pay off. You can download the app on the App Store now.

    The app now has its own official JIRA project! It’s great to see that I’ve made a lasting contribution to the community. I plan to keep improving it even after the contest, including possibly transferring it to Swift (with its better nil-safety features, awesome for preventing crashes.I’d consider this my biggest contribution to the OpenMRS community. In only three weeks, I was able to build, document, test, and submit an application to the App Store. For comparison, see this infographic – average app build time is 18 weeks. I didn’t have to build the server side, but I still built the app more than twice as fast as a full development studio would. This was a blast!Thanks to harshadura for leading me through the development and marketing of the app. You’re awesome!
  • Set up OpenMRS locallyFor some reason, I’ve never been very good at setting up large projects for the first time, often resorting to trial-and-error. This installation went without a hitch. Kudos to the OpenMRS developers for making it easy for even me to install!
  • Work on OpenMRS-ID’s UI. Spanning six tasks (1, 2, 3, 4, 5, 6), I worked on helping to overhaul openmrs-contrib-id‘s user interface in accordance with the new designs. I learned a lot from this set of tasks. I had never worked with Node before, and I learned a lot about how partials work, how the asset pipeline works, etc.I’d like to thank Elliott Williams for taking time out of his busy schedule to help me with these tasks!
  • Create a logo and splash screen for the iOS clientI’m first and foremost a developer, but I like to try my hand at design now and then. I proposed several icons and splash screens for the iOS app. I use GIMP for all my artwork, mainly because I’m too cheap to go buy Photoshop (and too honest to go pirate it).
  • Deploy OpenMRS to OpenShiftOpenShift is a Public PaaS (platform as a service) that you can run for free at its base tier. The low cost of this service makes it perfect for hospitals with low funding to run OpenMRS!I tested a guide document that another student had made for this, and suggested a couple improvements to it. I’m now confident that this guide will help make OpenMRS more accessible to medical institutions everywhere!
  • Improve the Modulus search algorithmI’ve never played with search beyond simple literal matching algorithms. I learned a lot about search optimizations, weighting, ordering, and sorting through this task, and proposed several improvements on the wiki page.
  • Find and correct bad practices in code through SonarSonar is an automated solution for ensuring code follows preset practices. This was the fist time I’d used it, and I think I will start using it in my future Java projects! I corrected several bad practices across the project and submitted my fixes as pull requests to the main repository.
  • Find and report two bugs in the systemI like to break things, especially when I’m supposed to break them. I found two bugs in OpenMRS, one a simple date formatting issue and the other a more serious injection issue involving patient names. I learned a lot about HTML injections doing this!
  • Identify UX improvementsI noticed some inconsistencies in one of the tables on OpenMRS and reported them on JIRA. One of them I was even able to fix with a little bit of CSS!
  • Fix a Modulus scrolling bug. In this task, I fixed a scrolling bug in Modulus. A page would automatically scroll to the bottom on every load, when it should only scroll to the bottom when it’s in the editing state.I had never worked on an AngularJS project before, and Elliott Williams helped me a great deal throughout the project. After completing that task, I feel I have a much better understanding of how Angular works. Thank you, Elliott!

Lessons Learnt:

I’ve never contributed to a large open source organization before. Here’s some of the things I learned:

  • It’s totally worth it. You meet amazing people doing amazing things, and you get to work with them and learn from them.
  • You can actually get stuff done. Before working with OpenMRS, I had the impression that large organizations, even open source ones, tend to take forever to make changes and review work and such. Not so here – things happen quickly, even with the relatively large size.
  • You have to add things to git before you commit. I.e., don’t go too fast. Do good work, not fast work. (See https://github.com/openmrs/openmrs-contrib-modulus-ui/pull/23#discussion_r23022640 for context)

And many more which aren’t covered here. If you’re reading this and you have any skill at all, go try contributing to an open source project. It’s worth it.

Overall Experience:

Overall, Google Code-In has been a great experience. OpenMRS has been extremely good to me as a student. I feel like a member of the community after less than two months. I’d like to thank each and every one of the mentors, specifically:

  • Harsha Siriwardena, for walking me through every step of creating the iOS app and surrounding documentation
  • Elliott Williams, for reviewing my OpenMRS ID and Modulus tasks. Also, for patiently giving me a crash course in Angular.
  • Robby O’Connor, for hanging out in IRC with us students and helpfully answering our questions.
  • Suranga Kasthurirathne, for helping me get OpenMRS set up at the beginning of the competition.
  • Harsha Kumara, for helping out with the Sonar bug-squashing tasks.

I don’t believe I had the privilege of directly interacting with the rest of the mentors – but I’m sure I’ll get to work with them in the coming months as I continue in my involvement in the OpenMRS community!

About that raw task count…

I haven’t done as many tasks as I could. I could have a much higher raw number of tasks, but that’s not what’s important to me. What’s important to me is that every line of code I write is maintainable, solid, testable (ideally tested as soon as I write it), and in general, good. I want to do good work, not a large amount of mediocre work. Google Code-In has helped cement that concept in me.

There were a few times when I was ‘stuck’ waiting for a mentor to review a task. It means I didn’t get as much done as I’d like to – but I’m fine with that. Mentors are people too, and they have busy lives. I used the time when I was waiting for a task to be reviewed to install new modules in my OpenMRS installation and experiment. I also used it to interact with the community. I plan to continue contributing for years to come.

The Future:

I believe that my most lasting contribution to OpenMRS will be the iOS app. It has an official JIRA project now. I’m looking forward to seeing the advancements the community as a whole can make in it!

There’s a development guide for the app on the OpenMRS wiki, and anyone can contribute. The next few years are going to be exciting as the community takes over the iOS app and makes improvements.

I also plan to continue contributing to OpenMRS myself, mostly through the iOS app and in working on various tickets for other projects.

I love how the OpenMRS community has handled Google Code-In, making every student feel welcome and a part of the community, and I hope some of them will stick around and continue contributing to the project. I know I will!

Running MySQL on an external hard drive

I recently found a need (fine, a want) to put the Stack Overflow data dump in a MySQL database. The posts table is very, very big, and my poor closet-laptop-server just doesn’t have enough room. I rummaged around and found a nice 1.5TB external hard drive to use.

One should be able to just point MySQL to any place one wants, right? In my case, I want the database to be stored in /media/bigdrive, where the big drive resides. Simple, right?

No.

After much Googling, I found this on DBA.SE:

  1. Shutdown mysql.
  2. Move all the files in your current data directory to the new location (check out the location in step 3 – datadir parameter).
  3. Locate my.ini file (it is in the mysql installation directory). Change datadir parameter value to point to the new location.
  4. Start mysql.

One would think these are really easy instructions to follow, but I somehow managed to completely destroy my main installation with them. Don’t ask how. It was a dev server, though, so nothing really important was in it.

Here’s my hopefully-foolproof method for doing this:

What I started with:

  • A fresh MySQL installation
  • Ubuntu Server 12.04
  • An intense desire to make this work

How I did it:

I decided to try to follow the above instructions again. After all, they have to work…

It’s a good idea to sudo su your way into root, because typing sudo is a lot of work and all programmers are lazy.

Shutting down MySQL is easy:

# service mysql stop
mysql stop/waiting

Next, we have to find the location of all those data files, which was helpfully not specified in the answer. A quick Googling found this question (from someone trying to do exactly what I’m doing), which says that the data is at /var/lib/mysql. That path might be different on your setup, consult Google.

A quick ls of the directory shows that it looks right:

# ls /var/lib/mysql
debian-5.5.flag  ib_logfile0  mysql       performance_schema
ibdata1      ib_logfile1  mysql_upgrade_info  test

The database I have on the server is named test, so I bet that this is the directory that holds all the MySQLy goodness.

We’ll just use cp to move the files to the 1.5TB drive:

# cp -r /var/lib/mysql /media/bigdrive/

It looks like the files made it across:

root@server1:/media/bigdrive/mysql# ls
debian-5.5.flag  ib_logfile0  mysql               performance_schema
ibdata1          ib_logfile1  mysql_upgrade_info  test

Next up is finding that my.ini file. Again, Google is your friend. It looks like no mention of a my.ini file was found, and instead it’s all my.cnf. Let’s go along with it and see what happens. This page says that the file is located at /etc/mysql/my.cnf (again, your milage may vary.)

We’re supposed to edit the datadir parameter in the file to our new directory. Opening the file up in vim (or whatever your favorite editor is) shows this, around line 40:

port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql // <- line 40
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql

I edited the datadir parameter to this:

datadir         = /media/bigdrive/mysql

And saved the file. Now, we need to restart MySQL:

root@server1:/etc/mysql# service mysql start
start: Job failed to start

I kind of expected something bad to happen, of course. I remembered something about AppArmor getting in the way from my previous readings, so I Googled it and found this answer on Ubuntu.SE (excerpt here):

If you open the file /etc/apparmor.d/usr.sbin.mysqld you will among the rules find these two lines.

/var/lib/mysql/ r,
/var/lib/mysql/** rwk,

Assuming our example above, they will have to be replaced or (probably preferable) complemented by these two lines.

/home/data/mysql/ r,
/home/data/mysql/** rwk,

Before we can startup our MySQL server, with its new datadir, we will also have to explicitly reload our new apparmor profile.

$ sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld

Following those instructions now:

# vim /etc/apparmor.d/usr.sbin.mysqld

For me, the lines were 32 & 33:

/var/lib/mysql/ r,
/var/lib/mysql/** rwk,

Which I edited to:

/media/bigdrive/mysql/ r,
/media/bigdrive/mysql/** rwk,

I saved the file and ran this command:

# apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld

After which….

# service mysql start
mysql start/running, process 10600

I can create tables and databases and insert and delete and everything.

Mission accomplished.