mirror of
https://github.com/flynx/pWiki.git
synced 2025-10-29 10:00:08 +00:00
experimenting with new index on paths/names...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
2129c967e5
commit
66e3c622b2
@ -24,10 +24,12 @@ var pwpath = require('../path')
|
||||
// - group operations:
|
||||
// - reset (cache) - DONE
|
||||
// - custom - DONE
|
||||
// XXX move .paths()/.names() to this...
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// makeIndex(<name>[, <options>])
|
||||
// makeIndex(<name>, <generate>[, <options>])
|
||||
// -> <index-handler>
|
||||
//
|
||||
@ -64,6 +66,10 @@ var pwpath = require('../path')
|
||||
// .__<name>_merge__(<data>)
|
||||
// -> <data>
|
||||
//
|
||||
// Test if cache is valid...
|
||||
// .__<name>_test__(<timestamp>)
|
||||
// -> <bool>
|
||||
//
|
||||
// Handle custom action...
|
||||
// .__<name>_<action-name>__(<data>. ...)
|
||||
// -> <data>
|
||||
@ -75,6 +81,9 @@ var pwpath = require('../path')
|
||||
// Cached data...
|
||||
// .__<name>_cache / .<name>
|
||||
//
|
||||
// Modification time...
|
||||
// .__<name>_modified
|
||||
//
|
||||
//
|
||||
// Options format:
|
||||
// {
|
||||
@ -100,9 +109,17 @@ var pwpath = require('../path')
|
||||
// }
|
||||
//
|
||||
//
|
||||
// XXX do we separate internal methods and actions???
|
||||
// i.e. __<name>_merge__(..) / __<name>_test__(..) and the rest...
|
||||
var makeIndex =
|
||||
module.makeIndex =
|
||||
function(name, generate, options={}){
|
||||
// makeIndex(<name>, <options>)
|
||||
if(generate
|
||||
&& typeof(generate) != 'function'){
|
||||
options = generate
|
||||
generate = options.generate }
|
||||
|
||||
// attr names...
|
||||
var cache =
|
||||
typeof(options.attr) == 'string' ?
|
||||
@ -112,14 +129,18 @@ function(name, generate, options={}){
|
||||
name
|
||||
: `__${name}_cache`
|
||||
var merge = `__${name}_merge__`
|
||||
var test = `__${name}_test__`
|
||||
var special = `__${name}__`
|
||||
var modified = `__${name}_modified`
|
||||
|
||||
// make local cache...
|
||||
var _make = function(){
|
||||
var res = this[special] != null ?
|
||||
this[special]()
|
||||
: generate.call(this)
|
||||
meth.modified = Date.now()
|
||||
var res =
|
||||
this[special] != null ?
|
||||
this[special]()
|
||||
: (generate
|
||||
&& generate.call(this))
|
||||
this[modified] = Date.now()
|
||||
return res }
|
||||
// unwrap a promised value into cache...
|
||||
var _await = function(obj, val){
|
||||
@ -140,14 +161,19 @@ function(name, generate, options={}){
|
||||
// action: clear...
|
||||
if(action == 'clear'){
|
||||
return }
|
||||
// check dependencies (timestamps)...
|
||||
if(cache in this
|
||||
&& meth.options.depends){
|
||||
var cur = meth.modified
|
||||
for(var dep of meth.options.depends){
|
||||
if(this[dep].modified > cur){
|
||||
delete this[cache]
|
||||
break } } }
|
||||
// validate cache...
|
||||
if(cache in this){
|
||||
var cur = this[modified]
|
||||
// user test...
|
||||
if(test in this
|
||||
&& !this[test](cur)){
|
||||
delete this[cache]
|
||||
// check dependencies...
|
||||
} else if(meth.options.depends){
|
||||
for(var dep of meth.options.depends){
|
||||
if(this[`__${this[dep].attr}_modified`] > cur){
|
||||
delete this[cache]
|
||||
break } } } }
|
||||
// action: other...
|
||||
if(action != 'get'
|
||||
&& action != 'reset'){
|
||||
@ -165,7 +191,7 @@ function(name, generate, options={}){
|
||||
options[action].call(this, cur, ...args)
|
||||
: cur)
|
||||
res !== cur
|
||||
&& (meth.modified = Date.now())
|
||||
&& (this[modified] = Date.now())
|
||||
return res }
|
||||
// action: get/local...
|
||||
return _await(this,
|
||||
@ -282,6 +308,14 @@ IndexManagerMixin({
|
||||
], }),
|
||||
get sum(){
|
||||
return this.__sum() },
|
||||
|
||||
__merged__: function(){
|
||||
return 777 },
|
||||
__merged_merge__: async function(data){
|
||||
return (await data) + 777 },
|
||||
__merged: makeIndex('merged'),
|
||||
get merged(){
|
||||
return this.__merged() },
|
||||
})
|
||||
|
||||
|
||||
@ -354,6 +388,7 @@ function(name, get, update, ...args){
|
||||
// -> <path-list>
|
||||
// .names()
|
||||
// -> <name-index>
|
||||
//
|
||||
// .exists(<path>)
|
||||
// -> <real-path>
|
||||
// -> false
|
||||
@ -427,10 +462,76 @@ module.BaseStore = {
|
||||
this.__data = value },
|
||||
|
||||
|
||||
// XXX INDEX...
|
||||
__xpaths__: async function(){
|
||||
return Object.keys(this.data) },
|
||||
// XXX unique???
|
||||
__xpaths_merge__: async function(data){
|
||||
return (await data)
|
||||
.concat((this.next
|
||||
&& 'xpaths' in this.next) ?
|
||||
await this.next.xpaths
|
||||
: []) },
|
||||
__xpaths_test__: function(t){
|
||||
var changed =
|
||||
!!this.__xpaths_next_exists != !!this.next
|
||||
|| (!!this.next
|
||||
&& this.next.__xpaths_modified > t)
|
||||
this.__xpaths_next_exists = !this.next
|
||||
return changed },
|
||||
__xpaths: makeIndex('xpaths', {
|
||||
update: async function(data, path){
|
||||
data = await data
|
||||
// XXX normalize???
|
||||
data.includes(path)
|
||||
|| data.push(path)
|
||||
return data },
|
||||
remove: async function(data, path){
|
||||
data = await data
|
||||
// XXX normalize???
|
||||
data.includes(path)
|
||||
&& data.splice(data.indexOf(path), 1)
|
||||
return data }, }),
|
||||
// XXX should this clone the data???
|
||||
get xpaths(){
|
||||
return this.__xpaths() },
|
||||
|
||||
// NOTE: this is build from .paths so there is no need to define a
|
||||
// way to merge...
|
||||
__xnames: makeIndex('xnames',
|
||||
function(){
|
||||
return this.xpaths
|
||||
.iter()
|
||||
.reduce(function(res, path){
|
||||
var n = pwpath.basename(path)
|
||||
if(!n.includes('*')){
|
||||
(res[n] = res[n] ?? []).push(path) }
|
||||
return res }, {}) }, {
|
||||
update: async function(data, path){
|
||||
data = await data
|
||||
// XXX normalize???
|
||||
var n = pwpath.basename(path)
|
||||
if(!n.includes('*')
|
||||
&& !data[n].includes(path)){
|
||||
(data[n] = data[n] ?? []).push(path) }
|
||||
return data },
|
||||
remove: async function(data, path){
|
||||
data = await data
|
||||
// XXX normalize???
|
||||
var n = pwpath.basename(path)
|
||||
data[n].includes(path)
|
||||
&& data[n].splice(data[n].indexOf(path), 1)
|
||||
data[n].length == 0
|
||||
&& (delete data[n])
|
||||
return data }, }),
|
||||
// XXX should this clone the data???
|
||||
get xnames(){
|
||||
return this.__xnames() },
|
||||
|
||||
|
||||
// XXX might be a good idea to cache this...
|
||||
__paths__: async function(){
|
||||
return Object.keys(this.data) },
|
||||
|
||||
// local paths...
|
||||
__paths: cached('paths', async function(){
|
||||
return this.__paths__() }),
|
||||
@ -442,6 +543,7 @@ module.BaseStore = {
|
||||
.concat((!local && (this.next || {}).paths) ?
|
||||
this.next.paths()
|
||||
: []) },
|
||||
|
||||
// XXX BUG: after caching this will ignore the local argument....
|
||||
names: cached('names', async function(local=false){
|
||||
return this.paths(local)
|
||||
@ -870,6 +972,7 @@ module.BaseStore = {
|
||||
: res },
|
||||
}
|
||||
|
||||
IndexManagerMixin(BaseStore)
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@ -952,6 +1055,38 @@ module.MetaStore = {
|
||||
// store adapters that can overload the level1 API to implement
|
||||
// their own stuff...
|
||||
|
||||
// XXX INDEX...
|
||||
__xpaths_merge__: async function(data){
|
||||
var that = this
|
||||
var stores = await Promise.iter(
|
||||
Object.entries(this.substores ?? {})
|
||||
.map(function([path, store]){
|
||||
return store.paths()
|
||||
.iter()
|
||||
.map(function(s){
|
||||
return pwpath.join(path, s) }) }))
|
||||
.flat()
|
||||
return object.parentCall(MetaStore.__xpaths_merge__, this, ...arguments)
|
||||
.iter()
|
||||
.concat(stores) },
|
||||
// XXX
|
||||
__xpaths_test__: function(t){
|
||||
if(!this.substores){
|
||||
return true }
|
||||
// match substore list...
|
||||
var cur = Object.keys(this.substores)
|
||||
var prev = this.__xpaths_substores
|
||||
if(!prev){
|
||||
this.__xpaths_substores = cur
|
||||
} else if(prev.length != cur.length
|
||||
|| (new Set([...cur, ...prev])).length != cur.length){
|
||||
return false }
|
||||
// check timestamps...
|
||||
for(var store of Object.values(this.substores ?? {})){
|
||||
if(store.__xpaths_modified > t){
|
||||
return false } }
|
||||
return object.parentCall(MetaStore.__xpaths_test__, this, ...arguments) },
|
||||
|
||||
paths: async function(){
|
||||
var that = this
|
||||
var stores = await Promise.iter(
|
||||
|
||||
@ -564,6 +564,20 @@ module.FileStoreRO = {
|
||||
return pwpath.join(...path)
|
||||
.replace(/\$PWIKI/, this.__pwiki_path__) },
|
||||
|
||||
// XXX INDEX...
|
||||
__xpaths__: async function(){
|
||||
var that = this
|
||||
return new Promise(function(resolve, reject){
|
||||
glob(pwpath.join(that.__path__, '**/*'))
|
||||
.on('end', function(paths){
|
||||
Promise.all(paths
|
||||
.map(async function(path){
|
||||
return await module.exists(path) ?
|
||||
decode(path)
|
||||
.slice(that.__path__.length)
|
||||
: [] }))
|
||||
.then(function(paths){
|
||||
resolve(paths.flat()) }) }) }) },
|
||||
// XXX do we remove the extension???
|
||||
// XXX cache???
|
||||
__paths__: async function(){
|
||||
|
||||
@ -33,6 +33,10 @@ module.IndexedDBStore = {
|
||||
return this.__data
|
||||
?? (this.__data = idb.createStore(this.__db__, this.__store__)) },
|
||||
|
||||
// XXX INDEX...
|
||||
__xpaths__: function(){
|
||||
return idb.keys(this.data) },
|
||||
|
||||
__paths__: function(){
|
||||
return idb.keys(this.data) },
|
||||
__exists__: function(path){
|
||||
|
||||
@ -29,6 +29,16 @@ module.localStorageStore = {
|
||||
localStorage
|
||||
: undefined,
|
||||
|
||||
// XXX INDEX...
|
||||
__xpaths__: function(){
|
||||
var that = this
|
||||
return Object.keys(this.data)
|
||||
.map(function(k){
|
||||
return k.startsWith(that.__prefix__) ?
|
||||
k.slice((that.__prefix__ ?? '').length)
|
||||
: [] })
|
||||
.flat() },
|
||||
|
||||
__paths__: function(){
|
||||
var that = this
|
||||
return Object.keys(this.data)
|
||||
|
||||
@ -34,6 +34,14 @@ module.PouchDBStore = {
|
||||
set data(value){
|
||||
this.__data = value },
|
||||
|
||||
// XXX INDEX...
|
||||
__xpaths__: async function(){
|
||||
var that = this
|
||||
// XXX not sure if this is a good idea...
|
||||
return (await this.data.allDocs()).rows
|
||||
.map(function(e){
|
||||
return e.id.slice(that.__key_prefix__.length) }) },
|
||||
|
||||
// XXX cache???
|
||||
__paths__: async function(){
|
||||
var that = this
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user