Skip to content

Commit

Permalink
fix(insight): enhance dependency display, fix #724
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 17, 2022
1 parent db346df commit 786a95d
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 27 deletions.
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
},
"dependencies": {
"@koishijs/utils": "^5.4.5",
"cordis": "^1.5.1",
"cordis": "^1.5.2",
"fastest-levenshtein": "^1.0.12",
"minato": "^1.2.0"
}
Expand Down
57 changes: 31 additions & 26 deletions plugins/frontend/insight/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,34 +73,33 @@ class Insight extends DataService<Insight.Payload> {
async get() {
const nodes: Insight.Node[] = []
const edges: Insight.Link[] = []
for (const runtime of this.ctx.app.registry.values()) {
// exclude plugins that don't work due to missing dependencies
const services = runtime.using.map(name => this.ctx[name])
if (services.some(x => !x)) continue

const rid = runtime.uid
const name = getName(runtime.plugin)
const deps = new Set(services.map(({ ctx }) => {
if (!ctx || ctx === ctx.app) return
return ctx.state.uid
}).filter(x => x))
for (const runtime of this.ctx.app.registry.values()) {
// Suppose we have the following types of nodes:
// - A, B: parent plugin states
// - X, Y: target fork states
// - M: target main state
// - S: service dependencies

// We divide plugins into three categories:
// We can divide plugins into three categories:
// 1. fully reusable plugins
// will be displayed as A -> X, B -> Y
// will be displayed as A -> X -> S, B -> Y -> S
// 2. partially reusable plugins
// will be displayed as A -> X -> M, B -> Y -> M
// will be displayed as A -> X -> M -> S, B -> Y -> M -> S
// 3. non-reusable plugins
// will be displayed as A -> M, B -> M
// where A, B: parent plugin states
// X, Y: target fork states
// M: target main state
// Service dependencies will be connected from the last node of each path
// will be displayed as A -> M -> S, B -> M -> S

function isActive(state: State) {
// exclude plugins that don't work due to missing dependencies
return runtime.using.every(name => state.context[name])
}

const name = getName(runtime.plugin)

function addNode(state: State) {
const { uid, alias, disposables } = state
const weight = disposables.length
const node = { uid, rid, name, weight }
const node = { uid, name, weight }
if (alias) node.name += ` <${format(alias)}>`
nodes.push(node)
}
Expand All @@ -109,24 +108,31 @@ class Insight extends DataService<Insight.Payload> {
edges.push({ type, source, target })
}

function addDeps(state: State) {
for (const name of runtime.using) {
const ctx = state.context[name][Context.source]
const uid = ctx?.state.uid
if (!uid) continue
addEdge('dashed', state.uid, uid)
}
}

const isReusable = runtime.plugin?.['reusable']
if (!isReusable) {
if (!isActive(runtime)) continue
addNode(runtime)
for (const target of deps) {
addEdge('dashed', runtime.uid, target)
}
addDeps(runtime)
}

for (const fork of runtime.children) {
if (runtime.isForkable) {
if (!isActive(fork)) continue
addNode(fork)
addEdge('solid', getSourceId(fork), fork.uid)
if (!isReusable) {
addEdge('solid', fork.uid, runtime.uid)
} else {
for (const target of deps) {
addEdge('dashed', fork.uid, target)
}
addDeps(fork)
}
} else {
nodes[nodes.length - 1].weight += fork.disposables.length
Expand All @@ -147,7 +153,6 @@ namespace Insight {

export interface Node {
uid: number
rid: number
name: string
weight: number
}
Expand Down

0 comments on commit 786a95d

Please sign in to comment.