Mesh level plugins - #236
Merged
Merged
Conversation
A mesh plugin bundles initialization for a whole mesh, which makes it the
home for cross-cutting concerns that belong to no single component. Since a
mesh is constructed empty and filled by AddComponents afterwards, a plugin
reaches components by registering an OnComponentAdded hook and instrumenting
each one as it arrives -- so it can observe every activation without any
component knowing it exists.
Storage, the duplicate-name check and the sorted init order now live in
internal/plugin.Registry[T], shared by both levels. Component plugins used to
initialize in map order; since plugins register hooks and hooks fire in
registration order, that order was observable and varied between runs of the
same binary. Both levels now sort by name.
Two plugins ship in plugin/:
- Profiler times runs, cycles and each component's activations. A Go CPU
profile of a mesh is dominated by the scheduler and barely distinguishes
one component from another; timing activations directly names the slow
one. Components activate concurrently and queue on the profiler's mutex,
so the start is stamped inside the lock and the end before it, keeping
that queueing out of the measured window.
- Autowire pipes ports by naming convention, in both directions on every
arrival, so AddComponents order does not matter. Pipes are not
deduplicated and a port flushes once per pipe, so it skips a pair that is
already wired -- two conventions agreeing on one pair would otherwise
deliver every signal twice.
Docs: .agent/docs/hooks.md covers both levels and the shared registry;
docs/wiki/502.-Plugins.md is the user-facing page, linked from Home and 501.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four components and five connections, with no PipeTo between components: two Autowire conventions derive the whole graph as components arrive, and the Profiler measures the result without any component opting in. The body is added before everything it listens to, so most of its wiring can only happen on the later arrivals -- the property that makes AddComponents order irrelevant. The clock's loopback is the one hand-written pipe, because a loopback is not something a naming convention can express. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
plugin.Prefixed("env_") says nothing about autowiring; at a call site inside
WithPlugins it could be anything. Broadcast and BroadcastAs had the same
problem, so all three are renamed together rather than leaving an inconsistent
family: AutowirePrefixed, AutowireBroadcast, AutowireBroadcastAs.
The PluginName strings ("autowire:prefixed:env_") already said it and are
unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Benchmark report (advisory)Statistically significant changes: 29 regression(s), 13 improvement(s) (PR head vs. base branch).
Higher is worse on every metric. Full benchstat table |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request refactors the plugin system to unify and document how plugins are registered and initialized for both components and meshes. It introduces a generic
plugin.Registryfor managing plugins, ensures plugins are initialized in sorted name order, and provides comprehensive documentation and tests. The changes improve consistency, extensibility, and observability of the plugin system.Plugin system refactor and registry introduction:
plugin.Registry(component/plugin.go,component/component.go,fmesh.go). This centralizes plugin management and ensures consistent behavior for both component and mesh plugins [1] [2].Documentation improvements:
.agent/docs/hooks.md,docs/wiki/502.-Plugins.md,docs/wiki/501.-Hooks.md,docs/wiki/Home.md) [1] [2] [3] [4] [5] [6]..agent/docs/hooks.md).Testing enhancements:
component/plugin_test.go) [1] [2].These changes make the plugin system more robust, predictable, and easier to use and extend.