# HG changeset patch # User drewp@bigasterisk.com # Date 2023-05-29 20:20:46 # Node ID 094e6b84b291041f25d5a414430343fd1f426fe4 # Parent 7796bc3e46b1c84d4367c9802d89455cdeac514e logging and refactor diff --git a/light9/web/AutoDependencies.ts b/light9/web/AutoDependencies.ts --- a/light9/web/AutoDependencies.ts +++ b/light9/web/AutoDependencies.ts @@ -33,6 +33,8 @@ export class AutoDependencies { // patterns). Top node is not a handler. this.handlers = new Handler(null, "root"); this.handlerStack = [this.handlers]; // currently running + log("window.ad"); + (window as any).ad = this; } runHandler(func: HandlerFunc, label: string) { @@ -53,9 +55,9 @@ export class AutoDependencies { // graph is initially loaded, which is a waste. Try deferring it if we // haven't gotten the graph yet. this._rerunHandler(h, /*patch=*/ undefined); + log(`new handler ${label} ran first time and requested ${h.patterns.length} pats`); } - //console.timeEnd("handler #{label}") - //@_logHandlerTree() + _rerunHandler(handler: Handler, patch?: Patch) { handler.patterns = []; this.handlerStack.push(handler); @@ -65,7 +67,7 @@ export class AutoDependencies { } handler.func(patch); } catch (e) { - log("error running handler: ", e); + this.graphError.emit(String(e)); } finally { // assuming here it didn't get to do all its queries, we could // add a *,*,*,* handler to call for sure the next time? @@ -76,15 +78,24 @@ export class AutoDependencies { // handler might have no watches, in which case we could forget about it logHandlerTree() { log("handler tree:"); - var prn = function (h: Handler, depth: number) { - let indent = ""; - for (let i = 0; i < depth; i++) { - indent += " "; + const shorten = (x: Term | null) => { + if (x === null) { + return "null"; + } + if (!Util.isNamedNode(x)) { + return x.value; } - log(`${indent} \"${h.label}\" ${h.patterns.length} pats`); - Array.from(h.innerHandlers).map((c: any) => prn(c, depth + 1)); + return this.graph.shorten(x as NamedNode); }; - prn(this.handlers, 0); + + var prn = (h: Handler, indent: string) => { + log(`${indent} 🤝 handler "${h.label}" ${h.patterns.length} pats`); + for (let pat of h.patterns) { + log(`${indent} ⣝ s=${shorten(pat.subject)} p=${shorten(pat.predicate)} o=${shorten(pat.object)}`); + } + Array.from(h.innerHandlers).map((c: any) => prn(c, indent + " ")); + }; + prn(this.handlers, ""); } _handlerIsAffected(child: Handler, patchSubjs: Set) { diff --git a/light9/web/RdfdbSyncedGraph.ts b/light9/web/RdfdbSyncedGraph.ts --- a/light9/web/RdfdbSyncedGraph.ts +++ b/light9/web/RdfdbSyncedGraph.ts @@ -1,22 +1,12 @@ import debug from "debug"; -import { html, LitElement, css } from "lit"; +import { LitElement, css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; -import { NamedNode } from "n3"; -import { Patch } from "./patch"; import { SyncedGraph } from "./SyncedGraph"; const log = debug("syncedgraph-el"); -// todo: consider if this has anything to contribute: -// https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md -let setTopGraph: (sg: SyncedGraph) => void; -(window as any).topSyncedGraph = new Promise((res, rej) => { - setTopGraph = res; -}); - -// Contains a SyncedGraph, -// displays a little status box, -// and emits 'changed' events with the graph and latest patch when it changes +// Contains a SyncedGraph. Displays as little status box. +// Put one element on your page and use getTopGraph everywhere. @customElement("rdfdb-synced-graph") export class RdfdbSyncedGraph extends LitElement { @property() graph: SyncedGraph; @@ -37,10 +27,6 @@ export class RdfdbSyncedGraph extends Li return html`graph: ${this.status}`; } - onClear() { - console.log("reset"); - } - constructor() { super(); this.status = "startup"; @@ -52,17 +38,23 @@ export class RdfdbSyncedGraph extends Li ["xsd", "http://www.w3.org/2001/XMLSchema#"], ]); this.graph = new SyncedGraph( - this.testGraph ? null : "/rdfdb/api/syncedGraph", + this.testGraph ? "unused" : "/rdfdb/api/syncedGraph", prefixes, (s: string) => { this.status = s; - }, - this.onClear.bind(this) + } ); setTopGraph(this.graph); } } +// todo: consider if this has anything to contribute: +// https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md +let setTopGraph: (sg: SyncedGraph) => void; +(window as any).topSyncedGraph = new Promise((res, rej) => { + setTopGraph = res; +}); + export async function getTopGraph(): Promise { const s = (window as any).topSyncedGraph; return await s; diff --git a/light9/web/SyncedGraph.ts b/light9/web/SyncedGraph.ts --- a/light9/web/SyncedGraph.ts +++ b/light9/web/SyncedGraph.ts @@ -31,8 +31,6 @@ export class SyncedGraph { patchSenderUrl: string, // prefixes can be used in Uri(curie) calls. This mapping may grow during loadTrig calls. public prefixes: Map, - // called if we clear the graph - private clearCb: any private setStatus: (status: string) => void ) { this.prefixFuncs = this.rebuildPrefixFuncs(prefixes); @@ -61,9 +59,6 @@ export class SyncedGraph { log("clearGraphOnNewConnection"); this.clearGraph(); log("clearGraphOnNewConnection done"); - if (this.clearCb != null) { - return this.clearCb(); - } } private rebuildPrefixFuncs(prefixes: Map) { @@ -171,6 +166,7 @@ export class SyncedGraph { this.cachedUriValues.clear(); patch.applyToGraph(this.graph); log("applied patch locally", patch.summary()); + log('dump:\n'+patch.dump()); this.autoDeps.graphChanged(patch); } diff --git a/light9/web/patch.ts b/light9/web/patch.ts --- a/light9/web/patch.ts +++ b/light9/web/patch.ts @@ -73,6 +73,24 @@ export class Patch { return "-" + this.dels.length + " +" + this.adds.length; } + dump(): string { + const lines: string[] = []; + const s = (term: N3.Term): string => { + if (term.termType=='Literal') return term.value; + if (term.termType=='NamedNode') return term.value + .replace("http://light9.bigasterisk.com/effect/","effect:") + .replace("http://light9.bigasterisk.com/",":") + .replace("http://www.w3.org/2000/01/rdf-schema#","rdfs:") + .replace("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf:") + if (term.termType=='BlankNode') return '_:'+term.value; + return term.id; + }; + this.dels.forEach((d) => lines.push("- " + s(d.subject) + " " + s(d.predicate) + " " + s(d.object))); + this.adds.forEach((d) => lines.push("+ " + s(d.subject) + " " + s(d.predicate) + " " + s(d.object))); + lines.sort(); + return lines.join("\n"); + } + async toJsonPatch(): Promise { return new Promise((res, rej) => { const out: SyncgraphPatchMessage = { patch: { adds: "", deletes: "" } };