diff --git a/pwiki/page.js b/pwiki/page.js index 986625a..039db4e 100755 --- a/pwiki/page.js +++ b/pwiki/page.js @@ -541,7 +541,10 @@ object.Constructor('Page', BasePage, { get depends(){ return (this.dependencies ?? {})[this.path] }, set depends(value){ - ;(this.dependencies = this.dependencies ?? {})[this.path] = value }, + if(value == null){ + delete (this.dependencies ?? {})[this.path] + } else { + ;(this.dependencies = this.dependencies ?? {})[this.path] = value } }, // The page that started the current render... // @@ -1077,15 +1080,20 @@ object.Constructor('Page', BasePage, { join = join && await base.parse(join, state) + // XXX DEPENDS... + // NOTE: thie does not introduce a dependency on each + // of the iterated pages, that is handled by the + // respective include/source/.. macros, this however + // only depends on page count... + depends.add(src) + // expand matches... var first = true for await(var page of this.get(src).asPages(strict)){ if(join && !first){ yield join } first = false - yield this.__parser__.expand(page, text, state) - // XXX DEPENDS... - depends.add(page.path) } + yield this.__parser__.expand(page, text, state) } // else... if(first && (text || args['else'])){ @@ -1258,13 +1266,108 @@ object.Constructor('Page', BasePage, { +//--------------------------------------------------------------------- + +// XXX this is good enough on the front-side to think about making the +// cache persistent with a very large timeout (if set at all), but +// we are not tracking changes on the store-side... +var CachedPage = +module.CachedPage = +object.Constructor('CachedPage', Page, { + // XXX should this always refer to .render_root.cachestore + cachestore: undefined, + /*/ + get cachestore(){ + return (this.render_root ?? this).__cachestore }, + set cachestore(value){ + ;(this.render_root ?? this).__cachestore = value }, + //*/ + + // NOTE: set this to null/undefined/0 to disable... + cache_timeout: '20m', + + get cache(){ + this.chechCache(this.path) + return ((this.cachestore ?? {})[this.path] ?? {}).value }, + set cache(value){ + if(this.cachestore === false + || this.cache == value){ + return } + var path = this.path + if(value == null){ + delete (this.cachestore ?? {})[path] + } else { + ;(this.cachestore = this.cachestore ?? {})[path] = { + created: Date.now(), + // XXX + valid: undefined, + value, + } } + // clear depended pages from cache... + for(var [key, deps] of Object.entries(this.dependencies)){ + if(key != path && deps.has(path)){ + //console.log('CACHE: DROP:', key) + delete this.cachestore[key] } } }, + + // XXX should this return something useful??? + chechCache: function(...paths){ + if(!this.cache_timeout || !this.cachestore){ + return this } + paths = paths.length == 0 ? + Object.keys(this.cachestore) + : paths + for(var path of paths){ + var {created, valid, value} = this.cachestore[path] ?? {} + if(value){ + var now = Date.now() + valid = valid + ?? Date.str2ms(this.cache_timeout) + // drop cache... + if(now > created + valid){ + //console.log('CACHE: DROP:', this.path) + delete this.cachestore[path] } } } + return this }, + + __update__: function(){ + this.cache = null + return object.parentCall(CachedPage.prototype.__update__, this, ...arguments) }, + __delete__: function(){ + this.cache = null + return object.parentCall(CachedPage.prototype.__delete__, this, ...arguments) }, + + get text(){ + var that = this + + /* XXX + console.log( + this.cache ? + 'CACHED:' + : 'RENDER:', + this.path) + //*/ + + var text = this.cache + ?? object.parentProperty(CachedPage.prototype, 'text').get.call(this) + text instanceof Promise + && text.then(function(text){ + that.cache = text }) + return text }, + set text(value){ + object.parentProperty(CachedPage.prototype, 'text').set.call(this, value) }, +}) + + //--------------------------------------------------------------------- var wikiword = require('./dom/wikiword') var pWikiPageElement = module.pWikiPageElement = +/* XXX CACHE... object.Constructor('pWikiPageElement', Page, { +/*/ +object.Constructor('pWikiPageElement', CachedPage, { +//*/ dom: undefined, @@ -1273,7 +1376,8 @@ object.Constructor('pWikiPageElement', Page, { wikiword: wikiword.wikiWordText, }, - __clone_constructor__: Page, + //__clone_constructor__: Page, + __clone_constructor__: CachedPage, __clone_proto: undefined, get __clone_proto__(){ @@ -1320,7 +1424,16 @@ object.Constructor('pWikiPageElement', Page, { onLoad: types.event.Event('onLoad', function(){ this.dom.dispatchEvent(this.__pWikiLoadedDOMEvent) }), - refresh: async function(){ + // XXX CACHE... + __last_refresh_path: undefined, + refresh: async function(full=false){ + // drop cache if re-refreshing or when full refresh requested... + // XXX CACHE... + ;(full + || this.__last_refresh_path == this.path) + && this.cache + && (this.cache = null) + this.__last_refresh_path = this.path var dom = this.dom dom.innerHTML = await this.text for(var filter of Object.values(this.domFilters)){ @@ -1372,7 +1485,11 @@ module.System = { text: '@include(. isolated join="@source(file-separator)")' }, _view: { text: object.doc` - /list @source(./path)/_edit + + + @source(./path) + (edit) +

diff --git a/pwiki2.js b/pwiki2.js index 25fc494..05981a4 100755 --- a/pwiki2.js +++ b/pwiki2.js @@ -1,6 +1,7 @@ /********************************************************************** * * +* XXX CACHE track store changes... * XXX need a uniform way to track some state in links in pwiki for things * like paging and the like with simple user/macro access (???)... * ...the simplest that comes to mind is to store in in path @@ -34,8 +35,6 @@ * - session * - stored (config) * ...css selector as path.... -* XXX CACHE cache rendered pages and invalidate cache based to changes -* to page dependencies... * XXX GENERATOR make pattern path parsing a generator... * ...experiment with a controllable iterator/range thing... * This would require: @@ -52,6 +51,13 @@ * ...might be a good idea to make filters local only... * XXX slots/macros might also pose a problem... * 2) all the macros that can source pages to produce generators (DONE) +* XXX the parser should handle all action return values, including: +* - lists -- DONE +* - iterators -- DONE +* - strings -- DONE +* - numbers -- DONE +* - misc: +* dates -- ??? * XXX BUG: .move(..) behaves in an odd way... * see: System/move page action * ...deletes the original and moves an empty page -- sync error??? @@ -81,6 +87,8 @@ * ...looks like no :| * XXX DEPENDS @now() makes the template uncachable, to we actually need it??? * XXX CHECK: @macro(..) and @slot(..) must overload in the same way... +* XXX DEPENDS/CACHE @macro(..) introduces a dependency on count (pattern) +* ...not sure how we track these... * * *