tiddlywebplugins.fastly
is a TiddlyWeb
plugin that works with the Fastly dynamic CDN to
effectively cache single
recipes,
bags, tiddlers and collections thereof.
See the design notes for background info.
This plugin is an experiment to explore what hurdles need to be overcome to get TiddlyWeb working in the Fastly context and generally to explore the Fastly ecosystem.
For fast.
Depending on the usage profile (the ratio of reads to writes) of the TiddlyWeb service the number of hits against the backend will drop dramatically and the effective latency for the end user will be significantly improved. This means the backend can be quite lightweight while still providing zoom to the users.
An existing TiddlyWeb instance can be updated to use this plugin as follows (note: The second step is not yet true as the plugin has not been released to PyPI yet, please clone this repo and install from there):
-
Install fastly-py.
-
Install the plugin:
pip install -U tiddlywebplugins.fastly
. -
Edit tiddlywebconfig.py to add
tiddlywebplugins.fastly
to system_plugins and twanager_plugins and add keys and values forfastly.server_id
andfastly.api_key
(found in the analytics and configuration app at http://fastly.com/:'system_plugins': ['tiddlywebwiki', 'tiddlywebwplugins.fastly'], 'twanager_plugins': ['tiddlywebwiki', 'tiddlywebwplugins.fastly'], 'fastly.server_id': 'your_server_id', 'fastly.api_key': 'your_api_key'
-
Restart the instance.
Once installed three new pieces of functionality will be present:
- There are several new
twanager commands for
inspecting and manipulating the Fastly configuration and manually
purging URLs and keys. Run
twanager
to see them listed. - Outgoing responses to
GET
requests are augmented with appropriateSurrogate-Key
headers. - When entities are written to the store (via
store.put
) aHOOK
sends apurge_key
request to the Fastly API.
By default Fastly will cache anything you give it. If you need to
avoid this you can write custom VCL for various rules that will cause
a pass
. One convenient catch-all is to pass
on anything which has
not provided a Surrogate-Key
header:
if ( !beresp.http.surrogate-key ) {
set beresp.ttl = 0s;
set beresp.grace = 0s;
return(pass);
}
This, however, is a sledgehammer. It is generally better to let most
URIs cache and configure pass
on specific URIs.
The code for surrogate keys can be extended to generate keys for custom routes provided by plugins. For example to generate keys for the friendlywiki route provided by tiddlywebwiki a plugin with the following code could be used:
from tiddlywebplugins.fastly.surrogates import recipe_tiddlers_uri_keys
def init(config):
def friendly_keys(environ, start_response):
return recipe_tiddlers_uri_keys(environ)
config['fastly.selector'].add('/{recipe_name:segment}', GET=friendly_keys)
This is a hack to utilize the WSGI dispatching routines in
Selector to call a function
which returns a list of keys. The function should return whatever keys
make sense for the given route. In this example since the route
returns a collection of tiddlers generated by a recipe the
recipe_tiddlers_uri_keys
method is used.
At this time the plugin is not fully complete: Authenticated scenarios are not handled. See the design notes for comments on authentication.
If you need a quick fix for dealing with Auth you can add cookies to the request hash. This will create a per user cache. See: