dbug: allow custom state queries

Try to give state version number on first load. Run custom queries on
demand, similar to +dbug [%state 'whatever'].
This commit is contained in:
Fang 2020-05-20 21:13:18 +02:00
parent 15e3ea6940
commit da4274d490
No known key found for this signature in database
GPG Key ID: EB035760C1BBA972
5 changed files with 165 additions and 47 deletions

View File

@ -153,57 +153,81 @@
(as-octt:mimes (en-json u.json))
=, enjs:format
?+ site ~
:: /app.json: {appname: running, ...}
:: /apps.json: {appname: running?}
::
[%app ~]
[%apps ~]
%- some
%- pairs
%+ turn all:apps
|= app=term
[app b+(running:apps app)]
::
:: /app/[appname].json: {state: }
:: /app/[appname]...
::
[%app @ ~]
[%app @ *]
=* app i.t.site
::TODO ?. (dbugable:apps app) ~
%- some
%- pairs
:~ :- 'state'
(tank (sell (state:apps app)))
=/ rest=^path t.t.site
?+ rest ~
:: /app/[appname].json: {state: }
::
:- 'subscriptions'
%- pairs
=+ (subscriptions:apps app)
|^ ~['in'^(incoming in) 'out'^(outgoing out)]
~
%- some
%- pairs
:~ :- 'simpleState'
%- tank
=; head=(unit ^tank)
(fall head leaf+"unversioned")
:: try to print the state version
::
=/ version=(unit vase)
(slew 2 (state:apps app))
?~ version ~
?. ?=(%atom -.p.u.version) ~
`(sell u.version)
::
++ incoming
|= =bitt:gall
^- json
:- %a
%+ turn ~(tap by bitt)
|= [d=duct [s=^ship p=^path]]
:- 'subscriptions'
%- pairs
~! (ship s)
:~ 'duct'^a+(turn d path)
'ship'^(ship s)
'path'^(path p)
==
::
++ outgoing
|= =boat:gall
^- json
:- %a
%+ turn ~(tap by boat)
|= [[w=wire s=^ship t=term] [a=? p=^path]]
%- pairs
:~ 'wire'^(path w)
'ship'^(ship s)
'app'^s+t
'acked'^b+a
'path'^(path p)
==
--
=+ (subscriptions:apps app)
|^ ~['in'^(incoming in) 'out'^(outgoing out)]
::
++ incoming
|= =bitt:gall
^- json
:- %a
%+ turn ~(tap by bitt)
|= [d=duct [s=^ship p=^path]]
%- pairs
:~ 'duct'^a+(turn d path)
'ship'^(ship s)
'path'^(path p)
==
::
++ outgoing
|= =boat:gall
^- json
:- %a
%+ turn ~(tap by boat)
|= [[w=wire s=^ship t=term] [a=? p=^path]]
%- pairs
:~ 'wire'^(path w)
'ship'^(ship s)
'app'^s+t
'acked'^b+a
'path'^(path p)
==
--
==
::
:: /app/[appname]/state.json
:: /app/[appname]/state/[query].json
::
[%state ?(~ [@ ~])]
%- some
=- (pairs 'state'^(tank -) ~)
%+ state-at:apps app
?~ t.rest ~
(slaw %t i.t.rest)
==
::
:: /spider.json
@ -335,17 +359,33 @@
::
++ state
|= app=term
(scry-dbug vase app /dbug/state)
^- vase
(scry-dbug vase app /state)
::
++ state-at
|= [app=term what=(unit @t)]
^- tank
=/ state=vase (state app)
?~ what (sell state)
=/ result=(each vase tang)
%- mule |.
%+ slap
(slop state !>([bowl=bowl ..zuse]))
(ream u.what)
?- -.result
%& (sell p.result)
%| (head p.result)
==
::
++ subscriptions
=, gall
|= app=term
^- [out=boat in=bitt]
(scry-dbug ,[boat bitt] app /dbug/subscriptions)
(scry-dbug ,[boat bitt] app /subscriptions)
::
++ scry-dbug
|* [=mold app=term =path]
(scry mold %gx app (snoc `^path`path %noun))
(scry mold %gx app (snoc `^path`[%dbug path] %noun))
::
::TODO but why? we can't tell if it's on or not
++ poke-verb-toggle

View File

@ -3,6 +3,7 @@ import ReactDOM from 'react-dom';
import _ from 'lodash';
import { store } from '/store';
import moment from 'moment';
import { stringToTa } from './lib/util';
class UrbitApi {
@ -113,9 +114,7 @@ class UrbitApi {
// apps
getApps() {
//TODO onfail render "failed to fetch apps"
//TODO generic "fail" local event that prints to status bar?
this.getJson('/app',
this.getJson('/apps',
this.wrapLocal('apps'),
this.showStatus('error fetching apps')
);
@ -132,6 +131,19 @@ class UrbitApi {
);
}
getAppState(app, state = '') {
if (state !== '') {
state = '/' + stringToTa(state)
}
this.getJson('/app/'+app+'/state'+state, (data) => {
data.app = app;
return this.wrapLocal('appState')(data);
},
() => { // on fail
store.handleEvent({data: { local: { 'appFailed': app } }});
});
}
// spider
getThreads() {

View File

@ -30,3 +30,41 @@ export function msToDa(ms, mil) {
export function renderDuct(duct) {
return duct.reduce((a, b) => a + b + ' ', '');
}
// encode the string into @ta-safe format, using logic from +wood.
// for example, 'some Chars!' becomes '~.some.~43.hars~21.'
// this is equivalent to (scot %t string)
//
export function stringToTa(string) {
let out = '';
for (let i = 0; i < string.length; i++) {
const char = string[i];
let add = '';
switch (char) {
case ' ':
add = '.';
break;
case '.':
add = '~.';
break;
case '~':
add = '~~';
break;
default:
const charCode = string.charCodeAt(i);
if (
(charCode >= 97 && charCode <= 122) || // a-z
(charCode >= 48 && charCode <= 57) || // 0-9
char === '-'
) {
add = char;
} else {
// TODO behavior for unicode doesn't match +wood's,
// but we can probably get away with that for now.
add = '~' + charCode.toString(16) + '.';
}
}
out = out + add;
}
return '~~' + out;
}

View File

@ -8,6 +8,7 @@ export class LocalReducer {
//
this.apps(data, state);
this.app(data, state);
this.appState(data, state);
this.appFailed(data, state);
this.verbResult(data, state);
this.verbStatus(data, state);
@ -48,10 +49,18 @@ export class LocalReducer {
app(obj, state) {
const data = _.get(obj, 'app', false);
if (data) {
if (state.apps[data.app]) data.state = state.apps[data.app].state;
state.apps[data.app] = data;
}
}
appState(obj, state) {
const data = _.get(obj, 'appState', false);
if (data) {
state.apps[data.app].state = data.state;
}
}
appFailed(obj, state) {
const data = _.get(obj, 'appFailed', false);
if (data) {

View File

@ -10,8 +10,11 @@ export class Apps extends Component {
constructor(props) {
super(props);
this.state = {};
this.state = {
stateQuery: {}
};
this.changeStateQuery = this.changeStateQuery.bind(this);
this.loadApps = this.loadApps.bind(this);
this.loadAppDetails = this.loadAppDetails.bind(this);
}
@ -27,6 +30,11 @@ export class Apps extends Component {
//
}
changeStateQuery(app, event) {
this.state.stateQuery[app] = event.target.value;
this.setState({ stateQuery: this.state.stateQuery });
}
loadApps() {
api.getApps();
}
@ -35,11 +43,14 @@ export class Apps extends Component {
api.getAppDetails(app);
}
loadAppState(app) {
api.getAppState(app, this.state.stateQuery[app]);
}
//TODO use classes for styling?
render() {
const { props, state } = this;
console.log('render', props.apps, Object.keys(props.apps));
const apps = Object.keys(props.apps).sort().map(app => {
const appData = props.apps[app];
const haveDeets = (typeof appData === 'object');
@ -71,8 +82,16 @@ export class Apps extends Component {
>
refresh
</button>
<button onClick={()=>{this.loadAppState(app)}}>query state</button>
<textarea
class="mono"
onChange={(e) => this.changeStateQuery(app, e)}
value={state.stateQuery[app]}
placeholder="-.-"
spellCheck="false"
/>
<div style={{maxHeight: '500px', overflow: 'scroll'}}>
<pre>{data.state.join('\n')}</pre>
<pre>{(data.state || data.simpleState).join('\n')}</pre>
</div>
<div>
<Subscriptions {...data.subscriptions} />