Tuesday, June 5, 2012

Cache OpenLayers Tiles With Web SQL Database

(Note: this post has been edited to reflect the current state of OpenLayers and my code.)

As of this edit, there's an open pull request to provide a pluggable offline cache system for OpenLayers.  A few months ago, there was only a single CacheRead/CacheWrite implementation using localstorage.  I needed Web SQL Database support because localstorage currently maxes out at 5MB on iOS (with ungraceful failures), whereas Web SQL Database will grow to 50MB with user confirmation.

ahocevar's pull request for the initial implementation indicated that adding backends for other databases would be as easy as providing a different implementation for OpenLayers.Control.CacheWrite.cache and OpenLayers.Control.CacheRead.fetch.  This is true...ish.  Because Web SQL Database is asynchronous (apparently no vendor ever implemented the synchronous API, at least on mobile), there are a lot of gotchas.  Rather than list them all here, I'll link again to my comment on the current pull request, where I note a few.

I got a public github account and committed some code before being asked for an OpenLayers Contributors License Agreement and learning that my university really has no process for approving things like that.  But since this blog post had already linked to my modified CacheWrite and CacheRead controls, I'm leaving the links live.  I've also committed my latest versions, which fix some bugs.  Feel free to use this code as a guide for OpenLayers caching code, but don't submit it verbatim to OpenLayers until I get a CLA.  Thanks!

Note that this code (and all OpenLayers caching code) is affected by an OpenLayers bug that allows slightly different URLs to be calculated for essentially the same tiles, leading to cache misses that should be hits.  Be my guest and fix this bug to make caching work more reliably!  (Read the issue comments to understand what the fix requires.)

Be aware that this code doesn't properly notify on "cachefull" situations.  At least on iOS, I found that there was no way to distinguish between a quota error and a unique constraint violation.  That is, inserts that fail due to exceeding the disk quota are reported as constraint violations.  I think this is a bug in Safari, but probably one that will never be fixed now that Web SQL Database is deprecated.

Happy coding!

No comments:

Post a Comment