Okay this is quite specialised by the four or five of you who will have the same problem I wanted to save you some time and suffering.
So Neo Technologies have been incubating a plugin of their excellent graph database on Heroku for a while. So far the plugin was only available in beta but now anyone can have it. This is excellent news and I would recommend it as a way of getting starting with graph-based web programming. However if you were in the beta program then you now need to migrate from the beta plugin to the new one.
The instructions that went out to the beta program implied that this was simply a case of dumping a backup zip, switching out plugins and then uploading your zip. Well the good news is that exporting and importing the zips works exactly as advertised but the bad news is that the two plugins are quite different in terms of the environment they expose. The beta plugin had an extensive list of variables that exposed the various parts of your hosted environment. The new one just exposes the variable NEO4J_URL which is a url to the server and contains an embedded username and password.
Now the new variable does actually encode all the information that the original manifest did but in a very limited way and your library is going to have to work quite hard to correctly construct the base urls and requests required to access the REST API. I’m not sure which libraries do do it (I presume the Java ones) but neither of the Python ones do.
I’m going to describe what you need to do for the neo4j-rest-client which is the one I use in my apps but it will probably be similar for py2neo which is what you might want to use if you want to use a lot of Cypher.
So the simplest way to explain the solution is code.
import urlparse from neo4jrestclient.client import GraphDatabase def extract_credentials(url): parsed_url = urlparse.urlparse(url) if parsed_url.username and parsed_url.password: return (parsed_url.username, parsed_url.password) return None GRAPH_URL = os.environ.get('NEO4J_URL', "http://localhost:7474") + "/db/data/" credentials = extract_credentials(GRAPH_URL) if credentials: db = GraphDatabase(GRAPH_URL, username = credentials, password = credentials) else: db = GraphDatabase(GRAPH_URL)
So the neo4j-rest-client library supports username and password credentials but doesn’t parse them out of the url itself. Fortunately urlparse makes this pretty trivial. The conditional pieces of the code deal with the situation where we are running locally, essentially if we can’t see the Heroku environment variables we want to fallback to the local case (most Heroku stuff works this way).
A more frustrating issue is the difference between the url of the server and the root resource for the REST API. Naturally these are not the same but few libraries handle been given the wrong url that gracefully. Since the host URL does return successfully you usually get some failure about parsing or unpacking the root document. Submitting a patch to detect where the url ends in db/data or not would seem to be the logical solution.
So this code should boot a successful wrapper around the REST interface and your app should work again.
Except, that there seems to be another issue in the registering and deregistering of the plugin manifests. What I have observed is that heroku config lists the beta environment variables and not the new values. So even if you do this the library still gets 404 errors on the root document (because it is looking for the Neo4J environment that has been deallocated).
So the best way to migrate your app in my view is:
- go to your current app and download a database backup
- create a new app with a temporary name (or something like my-app-2)
- carry out your code changes as described above
- load your new code into your instance
- upload your backup into the new instance
- if the app is working rename your old app (to something like my-app-old)
- name your new app whatever your old app was called
This seems easier and less hassle than migrating in place. Once the beta plugin is turned off you should be able to delete the old app.