Commit 2ca23f56 authored by Michał "rysiek" Woźniak's avatar Michał "rysiek" Woźniak
Browse files

WIP: major code cleanup allowing for more funky plugin processing (ref: #17)

parent 4d203b4e
Pipeline #1956 passed with stage
in 3 minutes and 45 seconds
/* ========================================================================= *\
|* === Stashing plugin using the Cache API === *|
\* ========================================================================= */
/**
* getting content from cache
*/
......
......@@ -150,6 +150,117 @@ if (typeof SamizdatInfo !== "object") {
}
/* ========================================================================= *\
|* === Main Brain of Samizdat === *|
\* ========================================================================= */
/**
* Cycles through all the plugins, in the order they got registered
* and returns a Promise resolving to a Response in case any of the plugins
* was able to get the resource
*
* url - string containing the URL we want to fetch
* useStashed - (not implemented yet; currently all plugins are used) use stashed resources; if false, only pull resources from live sources
* doStash - stash resources once fetched successfully; if false, do not stash pulled resources automagically
*/
let getResourceThroughSamizdat = (url, useStashed=true, doStash=true) => {
// make sure SamizdatInfo exists for the url
if (typeof SamizdatInfo.resources[url] === 'undefined') {
SamizdatInfo.resources[url] = new SamizdatResourceInfo(url)
console.log('+-- created SamizdatInfo.resources[' + url + ']')
}
// clear the error fetchError info
SamizdatInfo.resources[url].fetchError = null;
SamizdatInfo.resources[url].method = SamizdatPlugins[0].name // whatever the first plugin is called
/**
* this uses Array.reduce() to chain the SamizdatPlugins[]-generated Promises
* using the Promise the first registered plugin as the default value
*
* see: https://css-tricks.com/why-using-reduce-to-sequentially-resolve-promises-works/
*
* this also means that SamizdatPlugins[0].fetch() below will run first
* (counter-intutively!)
*/
return SamizdatPlugins.reduce(
(prevPromise, currentPlugin)=>{
return prevPromise.catch((error)=>{
// Fall back to Samizdat:
console.log("(COMMIT_UNKNOWN) Samizdat fallback handling after: ", error);
console.log('+-- URL : ' + url)
console.log('+-- method : ' + currentPlugin.name)
// record the error in SamizdatInfo (as a string)
SamizdatInfo.resources[url].fetchError = error.toString()
// this is very naïve and should in fact be handled inside the relevant plugin, probably
SamizdatInfo.resources[url].method = currentPlugin.name;
// use the plugin
return currentPlugin.fetch(url)
})
},
// this SamizdatPlugin[].fetch() will run first
// all other promises generated by SamizdatPlugins[] will be chained using catch() on it
SamizdatPlugins[0].fetch(url)
)
.then((response)=>{
// do we want to stash at all?
if (doStash) {
// find the first stashing plugin
for (i=0; i<SamizdatPlugins.length; i++) {
if (typeof SamizdatPlugins[i].stash === 'function') {
// yes, this returns a promise...
return SamizdatInfo.resources[url].method.then((method)=>{
// if we got this from the same stashing plugin in the first place, this is moot
if (method === SamizdatPlugins[i].name) {
console.log('(COMMIT_UNKNOWN) Not stashing, since resource is retrieved by a stashing plugin:', url);
return response
}
// ok, now we're in business
console.log('(COMMIT_UNKNOWN) Stashing a successful fetch of:', url);
console.log('+-- fetched using :', method)
console.log('+-- stashing using :', SamizdatPlugins[i].name)
// working on clone()'ed response so that the original one is not touched
// TODO: should a failed stashing break the flow here? probably not!
return SamizdatPlugins[i].stash(response.clone(), url)
.then((res)=>{
// original response will be needed further down
return response
})
})
}
}
}
// if we're here it means we went through the whole list of plugins
// and found not a single stashing plugin
// or we don't want to stash the resources in the first place
// that's fine, but let's make sure the response goes forth
return response
})
// a final catch... in case all plugins fail
.catch((err)=>{
console.log("(COMMIT_UNKNOWN) Samizdat also failed completely: ", err);
console.log('+-- URL : ' + url)
// cleanup
SamizdatInfo.resources[url].fetchError = err.toString()
// this is very naïve and should in fact be handled inside the relevant plugin, probably
SamizdatInfo.resources[url].method = null
// rethrow
throw err
})
// this is where we can attach a .then() that will run regardless of the result
// which could then:
// - cache the results or perform some other housekeeping in case of success
// - handle the error in case of failure
}
/* ========================================================================= *\
|* === Setting up the event handlers === *|
\* ========================================================================= */
self.addEventListener('install', event => {
// TODO: Might we want to have a local cache?
// "COMMIT_UNKNOWN" will be replaced with commit ID
......@@ -179,94 +290,7 @@ self.addEventListener('fetch', event => {
// clean the URL, removing any fragment identifier
var cleanURL = event.request.url.replace(/#.+$/, '');
// make sure SamizdatInfo exists for the cleanURL
if (typeof SamizdatInfo.resources[cleanURL] === 'undefined') {
SamizdatInfo.resources[cleanURL] = new SamizdatResourceInfo(cleanURL)
console.log('+-- created SamizdatInfo.resources[' + cleanURL + ']')
}
// clear the error fetchError info
SamizdatInfo.resources[cleanURL].fetchError = null;
SamizdatInfo.resources[cleanURL].method = SamizdatPlugins[0].name // whatever the first plugin is called
// GET requests to our own domain that are *not* #samizdat-info requests
// get handled by plugins in case of an error
return void event.respondWith(
/**
* this uses Array.reduce() to chain the SamizdatPlugins[]-generated Promises
* using the Promise the first registered plugin as the default value
*
* see: https://css-tricks.com/why-using-reduce-to-sequentially-resolve-promises-works/
*
* this also means that SamizdatPlugins[0].fetch() below will run first
* (counter-intutively!)
*/
SamizdatPlugins.reduce(
(prevPromise, currentPlugin)=>{
return prevPromise.catch((error)=>{
// Fall back to Samizdat:
console.log("(COMMIT_UNKNOWN) Samizdat fallback handling after: ", error);
console.log('+-- URL : ' + cleanURL)
console.log('+-- method : ' + currentPlugin.name)
// record the error in SamizdatInfo (as a string)
SamizdatInfo.resources[cleanURL].fetchError = error.toString()
// this is very naïve and should in fact be handled inside the relevant plugin, probably
SamizdatInfo.resources[cleanURL].method = currentPlugin.name;
// use the plugin
return currentPlugin.fetch(cleanURL)
})
},
// this SamizdatPlugin[].fetch() will run first
// all other promises generated by SamizdatPlugins[] will be chained using catch() on it
SamizdatPlugins[0].fetch(cleanURL)
)
.then((response)=>{
// find the first stashing plugin
for (i=0; i<SamizdatPlugins.length; i++) {
if (typeof SamizdatPlugins[i].stash === 'function') {
// yes, this returns a promise...
return SamizdatInfo.resources[cleanURL].method.then((method)=>{
// if we got this from the same stashing plugin in the first place, this is moot
if (method === SamizdatPlugins[i].name) {
console.log('(COMMIT_UNKNOWN) Not stashing, since resource is retrieved by a stashing plugin:', cleanURL);
return response
}
// ok, now we're in business
console.log('(COMMIT_UNKNOWN) Stashing a successful fetch of:', cleanURL);
console.log('+-- fetched using :', method)
console.log('+-- stashing using :', SamizdatPlugins[i].name)
// working on clone()'ed response so that the original one is not touched
// TODO: should a failed stashing break the flow here? probably not!
return SamizdatPlugins[i].stash(response.clone(), cleanURL)
.then((res)=>{
// original response will be needed further down
return response
})
})
}
}
// if we're here it means we went through the whole list of plugins
// and found not a single stashing plugin
// that's fine, but let's make sure the response goes forth
return response
})
// a final catch... in case all plugins fail
.catch((err)=>{
console.log("(COMMIT_UNKNOWN) Samizdat also failed completely: ", err);
console.log('+-- URL : ' + cleanURL)
// cleanup
SamizdatInfo.resources[cleanURL].fetchError = err.toString()
// this is very naïve and should in fact be handled inside the relevant plugin, probably
SamizdatInfo.resources[cleanURL].method = null
// rethrow
throw err
})
// this is where we can attach a .then() that will run regardless of the result
// which could then:
// - cache the results or perform some other housekeeping in case of success
// - handle the error in case of failure
);
return void event.respondWith(getResourceThroughSamizdat(cleanURL))
});
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment