Explore: promote the shared hyperd daemon into a reusable crate (back burner)
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 25/100
- issue の種類
- 機能追加
- 明瞭さ
- 説明が足りない
- 活発さ
- 活発
- 技術スタック
- rust
調査の方向性
Start with hyperdb-mcp/tests/attach_tests.rs and its Engine::new_no_daemon setup, then run the proposed two-connection experiment against one hyperd to determine whether attachments are visible across sessions. Read the endpoint-based APIs in hyperdb-api/src/connection.rs, connection_builder.rs, async_connection.rs, pool.rs, and grpc_connection.rs. Done requires the isolation and trust-boundary prerequisites to be resolved and the behavior captured in a permanent characterization test before crate work begins.
索引モデルが issue の本文から書いたものです。
説明
Status
Design exploration, on the back burner. Nothing here is approved or
scheduled. This issue exists so the thinking is not lost — an earlier draft was
withdrawn pending a separate prerequisite, and the useful conclusions are
recorded here instead.
Two of the conclusions are negative, and they are the interesting ones: the
headline framing of the original proposal turns out to be wrong in a specific
and useful way, and the most ambitious version of the feature should not be
built at all. A narrower subset is worth doing, and exactly one small piece of
it has a cost that rises at the 1.0.0 freeze whether or not the rest ever
happens.
The idea
hyperdb-mcp runs a resident hyperd that multiple MCP sessions share.
Discovery goes through a record in a state directory, liveness through a
localhost health/control port, and the daemon notices when hyperd dies and
restarts it under a bounded restart policy.
Every other consumer of hyperdb-api — tests, examples, CLI tools, the
benchmark suite, downstream applications — spawns a private hyperd through
HyperProcess::new.
Real engineering went into that daemon and it is under-leveraged. The proposal
was a mode meaning "use the shared daemon rather than spawning your own
hyperd", so that short-lived processes stop paying hyperd startup cost and
stop multiplying hyperd instances.
Who benefits
- Test suites. Hundreds of sequential server starts, one application, one
build. A recordedmake testrun was 121 s for 1515 tests, and the suite has
a large number of helper-backed spawn sites, so this is where startup cost is
paid most often. - Repeatedly-invoked CLIs. A tool called in a loop or a script pays a full
spawn per invocation against a short workload. - Warm serverless pools running the same function. Many short processes,
one trust domain — but only if the daemon survives between invocations, which
is platform-dependent.
Note what these have in common: the processes sharing the engine are the same
application, the same build, and the same trust domain. That observation drives
the rest of the design.
The key architectural finding
This is the most valuable conclusion in the exploration, and it reshapes
everything after it.
"Expose a new mode meaning use the shared daemon rather than spawning your own
hyperd" implies hyperdb-api cannot currently talk to a hyperd it does not
own. It can, and always could. Verified against the tree:
Connection::connect(endpoint, database_path, create_mode)takes a bare
endpoint string (hyperdb-api/src/connection.rs:247), as do
Connection::without_database.ConnectionBuilder::new(endpoint)is endpoint-based
(hyperdb-api/src/connection_builder.rs:78).AsyncConnection::connect(endpoint, database, mode)likewise
(hyperdb-api/src/async_connection.rs:80). There is noAsyncConnection
constructor taking aHyperProcessat all, so async callers already pass an
endpoint string.PoolConfig { endpoint, .. }andSyncPoolConfig { endpoint, .. }are
endpoint-based (hyperdb-api/src/pool.rs:232,:690);pool.rsdoes not
mentionHyperProcessanywhere.grpc::GrpcConnection::connect(endpoint, database_path)and its async twin
likewise (hyperdb-api/src/grpc_connection.rs:138,:350).- None of them hold a
HyperProcess, and none stophyperdon drop.
HyperProcessis the only type inhyperdb-apiwhoseDropstops the
process (hyperdb-api/src/process.rs:1125); no otherimpl Dropin the crate
touches engine lifetime. - The MCP's own daemon mode is built out of exactly that public path.
Engine::try_daemon_modecallsConnection::connect(endpoint, …)and stores
hyper: None, so itsDropstructurally cannot stop the shared engine
(hyperdb-mcp/src/engine.rs:606,:651).
So what is genuinely absent from hyperdb-api is much narrower than the
proposal assumes:
- Discovery — turning "the shared daemon, wherever it is" into an endpoint.
- Supervision — starting the daemon if absent, restarting
hyperdwhen it
dies, shutting down when idle.
Item 2 requires a daemon process, which requires a binary, argument parsing,
and a logging subscriber. hyperdb-api must not grow those — and, having no
feature flags by design (confirmed: hyperdb-api/Cargo.toml has no
[features] section at all), it could not gate them if it did.
The daemon is therefore a supervisor that consumes HyperProcess. It is a
higher layer than hyperdb-api, not a lower one. The assumed direction is
inverted:
Assumed: the daemon must move DOWN
hyperdb-mcp -> hyperdb-api -> daemon/* relocated into api or core [wrong]
Actual: the daemon belongs ABOVE
hyperdb-mcp -> hyperdb-daemon -> hyperdb-api
other consumers -> hyperdb-daemon
(CLIs, tests, scripts)
Consequence: in the minimum viable slice, hyperdb-api gains no public API,
no dependency, and nothing entering the 1.0 freeze. That is both the cheapest
answer and the correct one.
Where the code should live
A new hyperdb-daemon crate that depends on hyperdb-api, shipping a
client library plus a hyperdb-daemon binary behind a default = ["cli"]
feature — exactly mirroring hyperdb-bootstrap, which already sets that
precedent (default = ["cli"], cli = ["dep:clap", "dep:anyhow", "dep:tracing-subscriber"], consumable as a pure library with
default-features = false). hyperdb-mcp then depends on hyperdb-daemon and
drops its own daemon/*. Dependency direction is hyperdb-daemon → hyperdb-api,
the same direction hyperdb-mcp → hyperdb-api already goes, so no layering rule
bends.
Alternatives considered and rejected:
- Into
hyperdb-api— needs a binary, soclapand a subscriber, which
with no feature flags every user pays for; and it puts a resident-service
surface inside the 1.0 semver freeze. - Into
hyperdb-api-core— worse. That crate is positioned as
forever-internal and sits below the API; supervision is strictly above the
wire protocol. - A crate that
hyperdb-apidepends on — makes discovery a mandatory
transitive dependency for everyhyperdb-apiuser, most of whom will never
use it, with no flag available to opt out.
What stays in hyperdb-mcp is all of the policy: attachment replay, the
persistent/ephemeral database model, _table_catalog, the KV store, watched
directories, the doctor, and the product's own version-takeover UX. The
genuinely generic residue is the discovery record, the port scan, the
control-protocol shape, HyperProcess ownership with a restart limiter, and the
detached-spawn skeleton.
Isolation is the central open problem
Treat this as a prerequisite, not a detail to sort out during
implementation. It is the difference between a feature that is safe to offer
and one that is not.
The resource argument
memory_limit is a Hyper instance-global parameter, applied to the process
at startup through Parameters and documented as "Hyper's global memory limit",
default 80 % of host RAM (hyperdb-api/tests/stress_test/README.md:173,
hyperdb-api/tests/stress_test/simulation.rs:271). Searches for
soft_memory_limit, hard_memory_limit, admission control, or any per-session
limit find nothing.
There is no per-session resource isolation to configure. One tenant's
oversized query applies memory pressure to every other tenant on the same
instance, and there is no knob to prevent it, because the engine does not expose
one. This is not a gap in the daemon — it is a property of the engine, and it is
not fixable in this repository.
Blast radius
When a shared hyperd dies, every tenant loses in-flight transactions and
every session's attach state. The daemon restarts hyperd, but attachment
replay lives in hyperdb-mcp's AttachRegistry — it is product policy, not a
library guarantee. A library client would simply find its attachments silently
gone against a freshly restarted engine. Rebuilding session state after a
peer-induced restart would be a burden pushed onto every caller.
Related: the current version-takeover rule (a client whose version is strictly
greater terminates the incumbent daemon and respawns) is actively dangerous when
generalised. Application A on v1.2 would terminate the daemon that application B
on v1.1 is mid-transaction against. A library must never take over. If the
resident daemon speaks a compatible control protocol, use it as-is even if
older; if it does not, start a separate daemon rather than displacing the
incumbent. Deliberate takeover stays available as an explicit operator action in
the CLI, where a human is choosing it.
The recommended answer: cohort scoping
Do not multi-tenant. Key the daemon to a cohort — a caller-supplied
identifier defaulting to something derived from the calling application, rather
than to a global constant. Different cohorts get different daemons, different
hyperd processes, and therefore real isolation, while still getting the
warm-start sharing that motivated the whole idea.
<state-dir>/
daemons/
<cohort-hash>/
daemon.json
logs/
What this buys: multi-tenancy stops being a blocker and becomes a documented
boundary; the instance-global memory_limit problem stops being
cross-application; blast radius is scoped to one application's own processes;
and version skew mostly disappears, because a cohort is usually one build.
What it costs: a machine running five cohorts runs five hyperd processes,
which is worse than one and much better than one-per-process. That is the right
place on the curve, and it is honest about not being free.
Open experiment, currently unresolved
No test proves whether one session on a shared hyperd sees another
session's attached databases. The API models attach per connection
(attach_database/detach_database are Connection methods emitting
ATTACH/DETACH DATABASE), and the MCP's registry is per-process, so the
expectation is that it does not — but the expectation is untested.
The nearest existing evidence proves a different claim: every case in
hyperdb-mcp/tests/attach_tests.rs constructs engines via
Engine::new_no_daemon, i.e. two private engines, so what those tests show
is that attach state does not survive a new process.
The experiment is cheap and should be run before anything ships: two connections
to one hyperd; A attaches a file under an alias; B queries that alias and
also enumerates pg_catalog.pg_database. Land it as a permanent
characterization test whichever way it resolves, so the documented model has
evidence behind it. If B can see A's attachment, cohort scoping moves from
strongly recommended to mandatory.
Trust boundary — deferred
Trust boundary — deferred. Establishing an authentication and isolation
model for a shared engine is a prerequisite for this work and is being handled
separately outside this issue.
Proposed public API sketch
Additive, and living entirely in hyperdb-daemon. Note that the connect calls
below are today's unmodified hyperdb-api calls.
Callers have three genuinely different intentions and must be able to say which:
/// How to obtain a `hyperd` to talk to.
pub enum Acquisition {
/// Spawn a private `hyperd`. Today's behaviour; remains the default.
Private,
/// Use the shared cohort daemon. Fail if it cannot be reached or started.
Shared,
/// Prefer the shared cohort daemon; fall back to a private `hyperd`.
/// Never slower than `Private` by more than `fallback_deadline`.
SharedOrPrivate,
}
/// A `hyperd` obtained by either route. Knows whether it owns the process.
pub enum Engine {
Private(hyperdb_api::HyperProcess),
Shared(SharedEngine),
}
impl Engine {
/// libpq endpoint, usable with every `hyperdb-api` connect API.
pub fn endpoint(&self) -> &str;
pub fn connection_endpoint(&self) -> &ConnectionEndpoint;
pub fn acquired(&self) -> Acquired; // Private | Shared
/// Why `Shared` was declined, when `SharedOrPrivate` fell back.
pub fn fallback_reason(&self) -> Option<&FallbackReason>;
}
/// Drop releases the lease and stops heartbeating.
/// It does NOT stop `hyperd` — that asymmetry with `HyperProcess::drop` is
/// the whole point and is the invariant most worth testing.
pub struct SharedEngine { /* … */ }
#[non_exhaustive]
#[derive(Clone, Debug)]
pub struct Options {
pub cohort: Cohort,
pub state_dir: Option<PathBuf>,
pub idle_timeout: Option<Duration>, // Some(_) by default, unlike today
pub fallback_deadline: Duration,
pub hyperd_path: Option<PathBuf>,
pub parameters: Option<Parameters>, // applied only when we start it
}
pub fn acquire(how: Acquisition, options: &Options) -> Result<Engine>;
pub async fn acquire_async(how: Acquisition, options: &Options) -> Result<Engine>;
The central invariant
A shared engine's Drop must release its lease without stopping hyperd.
That is the deliberate asymmetry with HyperProcess::drop, and it is the single
most important property in the crate. The test that pins it should assert both
halves so it cannot pass by accident: acquire a shared engine, drop it, prove
the daemon and its hyperd are still alive and serving; then acquire a private
engine, drop it, prove hyperd exited.
This asymmetry is also why a non-stopping variant of HyperProcess is a
non-goal. HyperProcess::drop is load-bearing for the test suite —
TestConnection and TestServer both hold a HyperProcess field purely so
that scope exit reaps the server — so a non-stopping variant would silently
orphan a server per test. Shared handles must be a distinct type.
Other API notes
Optionsis#[non_exhaustive]deliberately.ChartOptionsinhyperdb-mcp
was found to be source-breaking to extend precisely because it was not, and
this crate will grow knobs.- No silent fallback.
Sharedreturns a typed error naming why (no
daemon reachable, spawn timed out, protocol unsupported).SharedOrPrivate
succeeds but reports which mode it got and why the preferred one was
declined, and logs atwarn. The MCP currently logs its fallback atdebug
and returnsOk(None), which is exactly why a ten-second stall in the
discovery path went unnoticed in normal operation (now fixed, #270). SharedOrPrivatecarries a deadline, sized from measurement, so the
preferring mode is provably not a pessimisation. This is a correctness
property, not a tuning knob.- Default
idle_timeoutshould beSome(_). Today's daemon defaults to
Noneand runs forever unless configured. That is right for a product that
wants to stay warm for its user and wrong for a library: acargo testrun
must not leave a resident service behind. - Prefer a lease over pure heartbeat idling. Heartbeat-only has a real
failure mode — a client that is alive but idle past the timeout has the engine
shut down underneath it. Clients would register on acquire and release on
drop, with the idle timer running only while the lease count is zero;
heartbeats remain the mechanism that expires leases held by processes that
died without releasing. This needs new control commands, hence a protocol
version bump. - Version the control protocol separately from the crate. Crate semver is
the wrong compatibility axis for a wire protocol, and #276 is the evidence.
Add an explicitprotocolinteger to the discovery record and the ping
response; a client supports protocol N and N-1, and a daemon advertising an
unsupported protocol is treated as absent rather than as an error, so the
client starts its own daemon instead of failing.
Before and after
The Connection::new line changes to Connection::connect; nothing else moves.
// today
let hyper = HyperProcess::new(None, None)?;
let conn = Connection::new(&hyper, "db.hyper", CreateMode::CreateIfNotExists)?;
// shared, or private if the daemon is unavailable
let engine = hyperdb_daemon::acquire(
Acquisition::SharedOrPrivate,
&Options::for_cohort("my-cli"),
)?;
let conn = Connection::connect(engine.endpoint(), "db.hyper", CreateMode::CreateIfNotExists)?;
if engine.acquired() == Acquired::Private {
tracing::warn!(reason = ?engine.fallback_reason(), "shared engine unavailable");
}
// and the pool needs no change at all
let pool = create_pool(PoolConfig::new(engine.endpoint(), "db.hyper"))?;
That pool line is the clearest illustration of the architectural finding:
connection pooling over a shared daemon works today, with no new API,
because PoolConfig.endpoint is already a string and the pool has never owned a
process.
The benefit is unmeasured, and measuring it should gate the work
The entire premise is that sharing saves startup cost. This repository does
not contain a measurement of hyperd spawn-to-usable wall clock. Both
benchmark documents were checked directly:
docs/BENCHMARK_GUIDE.mdmeasures throughput. Its onlyspawnhits are
spawn_blockingtask spawns and "task-spawn overhead".docs/hyperd-release-benchmarks.mdmentions "cold-start variance", but in
context that refers to insert-throughput variance, not process spawn.
The honest state is one figure from an adjacent code path and one CI upper
bound:
| Figure | What it actually measured | Source |
|---|---|---|
| ~156 ms | First embedded Hyper start in a proc-macro host | hyperdb-api-derive/README.md:216 |
| "10+ seconds under load" | CI upper bound, hyperd startup alone, "especially macOS" |
hyperdb-mcp/tests/daemon_tests.rs:1774 |
No hyperd memory figure exists anywhere in the repository — searches find
only benchmark-host RAM totals and a qualitative "reduced memory overhead"
claim in the MCP README.
This is not a reason to abandon the idea. It is a reason not to design against a
number nobody has, because the answer changes the design:
- If cold spawn is ~150 ms, the warm win per process is ~150 ms, and this is
worth doing only for workloads that pay it hundreds of times. - If cold spawn is seconds on the platforms people actually use, the win is
large and the feature is clearly justified. - If cold spawn is cheaper than the daemon's own cold-acquisition path, the
feature is net-negative for the first process and only ever wins on the
second — still fine, but it changes what the default should be.
How to measure it
- Time
HyperProcess::new(None, None)plus one trivial query to first row.
20 iterations, report median and p95, release build. - Both transports (
TransportMode::TcpandTransportMode::Ipc). - macOS and Linux, recording the exact host, the
hyperdversion from
hyperdb-bootstrap/hyperd-version.toml, and whether the page cache was warm. - Then time warm acquisition — discovery plus connect against an
already-running daemon — over the same iteration count. The delta between
those two medians is the per-process win, and warm acquisition is the number
the design actually needs, because discovery is not free either. - Separately time the degraded discovery paths, because they size
fallback_deadline: warm hit, dead-port timeout, and a full port scan. - Sample
hyperdRSS at idle and after a representative query, and total RSS
for N = 1, 4, 16 concurrent processes. Note the interaction:memory_limit
defaults to 80 % of host RAM and is instance-global, so N private processes
each believe they may use 80 % of the machine — which is an argument for
sharing on memory grounds that nobody has quantified. - Do not assert on a duration in a test. Print timings under
--nocapture
and assert nothing, following the existing spike pattern. A wall-clock
assertion is a flaky test on shared CI. - Record the methodology and figures in
docs/BENCHMARK_GUIDE.md. Do not
add a row todocs/hyperd-release-benchmarks.md— that file takes a row on a
hyperdpin bump or a material API change, and conflating a startup
measurement with it would make a future engine delta unattributable.
Where it pays off, and where it does not
| Workload shape | Verdict | Why |
|---|---|---|
| Test suite, hundreds of sequential server starts | Clear win | Pays spawn cost most often; single application and build |
| CLI invoked repeatedly in a loop or script | Clear win | Per-invocation spawn dominates a short workload |
| Serverless warm pool, same function | Likely win | Many short processes, one trust domain — if the daemon survives between invocations |
| Long-running server, one process | Neutral to negative | Spawn paid once; adds a discovery dependency, a second failure domain, and a peer that can take the engine down |
| Concurrent bulk ingest from several processes | Actively worse | See below |
| Unrelated applications sharing one engine | Do not | Instance-global memory_limit, shared blast radius |
The "actively worse" row is measured, not guessed. From
docs/BENCHMARK_GUIDE.md (Apple M3 Max, 96 GB, hyperd 0.0.26479,
2026-09-05, medians of 5):
| Workload | 1 connection | 4 connections | Direction |
|---|---|---|---|
AsyncArrowInserter, 100M rows |
68.90 M/s | 48.47 M/s | ~30 % worse |
query.full_scan, async |
24.91 M/s | 73.45 M/s | ~2× better |
query.filtered, async |
26.90 M/s | 48.31 M/s | better |
The guide states plainly that "Parallelism no longer helps Arrow inserts" —
single-connection AsyncArrowInserter outruns the 4-connection variant, "so
spending connections on an Arrow insert buys nothing on this host"
(docs/BENCHMARK_GUIDE.md:201). Read for this design: one hyperd serves
concurrent readers well and concurrent bulk writers poorly. A shared daemon
whose tenants are all ingesting will contend on exactly the workload where extra
connections already measure negative.
Two caveats on that reading. The guide warns the ×4 rows are
"order-of-magnitude only", with a ±20–61 % spread, because four workers contend
on a 14-core laptop. And the Windows figures invert the insert result
(single-connection AsyncArrowInserter 5.39 M/s versus 20.28 M/s at ×4 over
TCP), so the conclusion is host- and engine-version-specific, not universal.
The win is narrower than the original proposal implies. It is concentrated
in many-short-processes-same-application, which is real and worth serving, and
it is absent or negative for the single long-lived process that most library
users actually are.
Prerequisites and related work
- #242 — a live-but-unresponsive
hyperdis never recovered. This is a
prerequisite, not a follow-on. Reproduced by suspending the managed child
process: aSELECT 1blocked for over 30 s, the daemon kept seeing the
process as alive, and never restarted it. Acceptable for a tool a developer can restart; not
acceptable for a library that silently enrolled the caller in a resident
service. - #276 — should
hyperdb-mcp'sdaemon::*be public? Directly related, and
extracting the daemon into its own crate would resolve it. The
recommendation recorded on that issue was to narrow the surface, on the
evidence that crates.io reverse dependencies forhyperdb-mcpare zero,
no workspace crate depends on it, and the crate's ownlib.rsalready
declares it "not a documented API surface". Extraction gives that surface a
home in a crate whose stated job is exactly that, where it can carry its own
compatibility promise. - #118 — one engine mutex serializes every MCP tool call. Not part of this
work, but relevant if a shared daemon ever grows a single-lock front end. - The daemon has little elapsed field exposure, and macOS CI still skips its
crash-and-restart tests. Promoting it to a library capability while its
crash-recovery coverage runs on a subset of platforms is not defensible. This
is an argument for elapsed time, not more code.
Recommendation on timing
The user has put the broader feature on the back burner. The one piece with
a real deadline is the extraction.
- Extract
daemon/*intohyperdb-daemonbefore1.0.0. It removes a
public module fromhyperdb-mcp, which is free before1.0.0and a major
bump after. It is worth doing on #276's merits alone, independent of
whether any of the rest ever ships, and it is the cheapest piece — a move
plus a re-export decision. Scope discipline matters: it is a move, not a
redesign. The evidence that it worked is the existing daemon test suite
passing unchanged under the new crate, reported as a characterization rather
than dressed up as red-before-green. - Measure startup cost and
hyperdRSS. Cheap, and it gates whether any of
the rest is justified. - Resolve the deferred prerequisites — #242 and the trust-boundary work
being handled separately. - Then, if the measurement holds, ship cohort-scoped
acquire()as a
0.1.0of the new crate, after1.0.0, withPrivateas the default and no
silent fallback. - Do not build cross-application sharing. The instance-global
memory_limitand the shared blast radius make it indefensible, and neither
is fixable in this repository.
The highest-value follow-on, once numbers exist, is teaching the test helpers to
accept a shared engine — but the risk there is the whole phase. Tests
currently get a fresh engine each time, so sharing one means leaked state
between tests. Enumerate what leaks (temp tables, attach aliases, session
settings, memory pressure), prove per-test cleanup, convert one file, measure
the delta, and stop for review before converting the suite.
One hyperdb-api decision has a 1.0.0 deadline
Connection::new takes a concrete &HyperProcess:
pub fn new(instance: &HyperProcess, database_path: impl AsRef<Path>, create_mode: CreateMode) -> Result<Self>
If a shared-engine handle should ever be usable where a HyperProcess is
usable, that parameter must become a trait bound. Generalising a concrete
parameter to impl Trait is source-compatible for ordinary call sites but not
for turbofish or function-pointer uses, so it is cheapest to do — or decide
against — before the freeze.
The recommendation is not to do it. Connection::connect(endpoint, …)
already covers the shared case, and adding a trait purely for symmetry is
speculative generality; adding it later is a minor addition, since a new trait
plus a new inherent method breaks nothing. But it is the only identified
hyperdb-api change whose cost rises after 1.0.0, so it wants an explicit
human confirmation rather than a default.
Non-goals
- No remote or network daemon. Loopback and local IPC only. This is not a
hyperdbroker. - No cross-application sharing, per the isolation section.
- No attachment replay, catalog, KV store, doctor, or watched directories in
the new crate. That is MCP policy and stays there. - No replacement for
HyperProcess.Privateremains the default and
HyperProcess::dropkeeps stopping the process, because the test suite
depends on it. - No non-stopping variant of
HyperProcess. Shared handles are a distinct
type. - No feature flag on
hyperdb-api. Firm repository constraint; the design
satisfies it by adding nothing tohyperdb-apiat all. - No fix for #242 or #118 as part of this work — but #242 is a prerequisite
gate, not a follow-on. - No changes to release automation, crate versions, or the root changelog.
Open questions needing a human decision
- Does the measured benefit justify building this at all? Blocked on the
measurement above. This is the real go/no-go. - What is the default cohort? Derived from the executable path, from the
crate name, or a required explicit argument with no default? A path-derived
default silently splits cohorts when a binary is rebuilt to a different
location; a required argument is more honest but less ergonomic. - Leases, or heartbeat-only idle? Leases avoid shutting the engine out from
under an idle-but-live client, at the cost of new control commands and a
protocol bump. Is that complexity warranted in a first release, or is a
generous idle timeout plus heartbeats enough? - Should
Connection::newbe generalised to a trait before1.0.0?
Recommendation: no. Deadline:1.0.0. - Does the extraction re-export
daemonfromhyperdb-mcpfor
compatibility? Recommendation: no — a re-export preserves the surface the
change exists to remove, and #276 established no known downstream library
consumer. - Does
hyperdb-mcpkeep its version-takeover behaviour after extraction, or
does it become a CLI-only operator action? The MCP's binary-upgrade UX
currently depends on it. - Do the C++, Python, or Java Hyper APIs — or upstream Hyper itself — already
have a shared-instance concept? Nothing in this repository describes one,
but that is absence of evidence, and it rests on a grep of this tree. Needs
external verification before "novel" is claimed anywhere public, and
terminology should be aligned rather than invented if a concept already
exists.
Recorded from an offline design exploration and its phased plan, both verified
against the tree on 2026-09-06. The documents themselves are deliberately not
committed. Every code reference above was re-checked against the repository
before being repeated here.
- 主要言語
- Rust
- スター
- 2
- フォーク
- 2
- 平均マージ
- 12時間 2分
- マージ済み PR(30日)
- 60
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
tableau/hyper-api-rust のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
tableau/hyper-api-rust#294 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
tableau/hyper-api-rust#311 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
tableau/hyper-api-rust#305 ·
-
Windows Named Pipe: verify DACL denies other users, and measure read-path perf for MCP workloads オープン
難易度 4/5 3〜5日 初心者へのやさしさ 38/100
tableau/hyper-api-rust#302 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 72/100
tableau/hyper-api-rust#300 ·
tableau/hyper-api-rust の issue をすべて見る
似ている issue
-
bug github_actions
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
registrystack/registry-stack#1393 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
longbridge/gpui-kit#3223 ·
-
bug engine
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
rocky-data/rocky#2181 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
oasisprotocol/oasis-sdk#2523 ·
-
[indexer] [QA] Add a focused test for the new NonRetryableError / assertSocketAlive() behavior. オープンbot:ai-assisted component:indexer QA-roadmap status:untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
midnightntwrk/midnight-indexer#1557 ·