Twisted firestarter
I was going down an avenue of seeing if we could implement a better and easier caching for Docker registry utilizing Google Firestore.
Getting an ember
Everyone that teaches to make/create your own fire will tell you that one of the most difficult things is getting an ember. A small hot enough material that will ignite the rest of the fuel. Well for me that was getting the source code for Docker registry (aka distribution) and getting it to compile and making sure I had the dependencies. They use an old school way using this tool called vndr which I am not familiar with since I am not an old school Golang developer.
After making sure the vendor.conf
and vndr
could play nicely and getting sucked down the rabbit hole of GO111MODULE
to be switched off and what that does, in order to get my development environment to be able to follow the imports. So finally I have a somewhat working thing, but I cannot make changes yet. This actually brought back a memory of long ago trying to do some early Golang development. That is I like to separate out my dependencies and code. I think having a workspace of sorts that is your Git checkout and a whole separate other static dependency location is nice. For example, let us say you are working on two projects in Python.
One is your library you want to use and the other is a project utilizing that library. Then if you want to make a change to your library, you do not want to do it directly in the project utilizing the library. You would want to have changes being arbitrarily worked on for the library separate from the project utilizing it. On your machine you might have two Git folders, one the library and the other the project. Then the project might have a dependency file that imports the library. You could even specify the Git branch in there. So you make the changes to your library, commit and push to a new branch. Checkout a new branch in the project and update the dependency file to the new branch and see if it all works.
Then just having virtual environments makes the most sense to me as you do not want everyone to use the same version of something or have to be force to use the same version. I digress.
So since I have one folder that has my Git code, and another that is the dependency I thought I would do the naive thing and just clone the repo into where the dependency is currently held and work on the code with symlinks. Nope. That did not work. Then I tried to work directly in the dependency and that did not work.
At some point I just gave up on this and started to work without autocomplete, syntax highlighting and any IDE features whatsoever and just a glorified text editor is all I had.
Fanning the ember
However small the ember, I needed to fan it in order to get the flame. Now I wanted to introduce the Firebase to our codebase that is sharing code with the Docker registry codebase. In essence we use it as a library as well. So in my project I just added the Firebase, no problem there. That took like 5 minutes. Then however came the problem that the Docker codebase had an old dependency on the GCP stuff. That messed things up. It caused a conflict I could not fix in our project codebase alone. So I had to update the GCP stuff for Docker registry (distribution codebase).
That meant just updating the reference right? Nope. I had to refactor the GCS storage layer as well with the newer calls and make them as close as I could to being backwards compatible/feature parity. Thinking I have done so, I try to recompile my code but it still does not use the new dependency I laid out. I just did a stupid thing and forked the code into my own Github, then changed all references to point to my Github instead of Docker. I since learned you can remap this in go.mod
and probably also in vendor.conf
but yeah. My hair already looked liked the Prodigy at this point so I might as well stay committed.
So I got a nice code base to work off of, and add my Firestore to our project using that augmented Docker codebase. Done, there is a flame going, starting to get bigger.
Fire, fire
Then I check the differences between this Firestore cache layer and our Redis one. It is tremendous, huge and insanely obvious what we should do after I answered the question if it is actually faster. Every call to the Firestore API to get a response takes a minimal of 1 second since that is the rate limit. So yeah, get the bucket of water and a bucket of sand to cover up this fire to put it out immediately.
Now I will say, we could improve our algorithm in the codebase and bypass how Docker gets tags by making one giant query and sending it to Firestore making it that we only pay a cost of 1 second once to get everything and it would be blazing fast afterwards since we would have everything and it would need to be kept in memory though. So it is still faster to query and store things in Redis.