~bigbes/tarantool-etcd · issues

d7td0mgcv9aro8ppnkgknqnbn4saht8b · 84 rows

idcontent_hashtitledescriptiondesignacceptance_criterianotesstatuspriorityissue_typeassigneeestimated_minutescreated_atcreated_byownerupdated_atclosed_atclosed_by_sessionexternal_refspec_idcompaction_levelcompacted_atcompacted_at_commitoriginal_sizesenderephemeralwisp_typepinnedis_templatemol_typework_typesource_systemmetadatasource_repoclose_reasonevent_kindactortargetpayloadawait_typeawait_idtimeout_nswaitershook_beadrole_beadagent_statelast_activityrole_typerigdue_atdefer_untilno_historystarted_at
tarantool-etcd-hlx629cacff048485b7bfdb7696ef646a8c092fc87f720e2f43caae3e2bfd8170aeReplica route: watch-tail live syncAfter bootstrap, open a clientv3 Watch from the bootstrap watermark+1 over the whole keyspace and apply every event (PUT/DELETE) into the etcd_* spaces, advancing the local synced watermark per event header. Must handle: - Progress notifications (WithProgressNotify) to advance the watermark even when idle, and detect staleness. - ErrCompacted (code 11): upstream compacted past our position -> trigger a re-bootstrap (tarantool-etcd child) then resume. - Reconnect/backoff on upstream Unavailable; resume from last applied revision. - Ordering: apply events in revision order; the local revision counter tracks upstream mod_revision (see revision-alignment child). This is the steady-state engine of mirror mode.ErrCompacted=11 and progress-notify semantics are the ones we already understand from conformance work (see clientv3 quirks memory).open2taskNULLNULL2026-05-20T06:17:55ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:55ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-hx983339a7afd9423290ef9d2cd3efe2cd40957688e945103b127b1b1bbb8e52b4aiproto-impl: etcd_member_remove vs Cluster.MemberRemoveWrap the existing handler cluster.member_remove (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberRemove) as a Lua global etcd_member_remove callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_remove', wrap('cluster', 'member_remove')) under the appropriate service block; append 'etcd_member_remove' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Cluster.MemberRemove returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_member_remove is callable from net.box:call('etcd_member_remove', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/cluster.lua.open3taskNULLNULL2026-05-19T14:54:21ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:21ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-iij291c145ebcd3fb5899f03f83ed0a7ad011df3459d5a8ed30498483aef3cd726fiproto-verify: etcd_lock vs Lock.LockAdd Lua testkit verification for etcd_lock (mirrors gRPC Lock.Lock). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/lock. Call shape: local resp = etcd_lock(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:17ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:17ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-iz4362238cde2d5629a32ed5166d55ec1085d0b4eb2cc0715b0eab59a0ab734967fiproto-verify: etcd_role_grant_permission vs Auth.RoleGrantPermissionAdd Lua testkit verification for etcd_role_grant_permission (mirrors gRPC Auth.RoleGrantPermission). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_role_grant_permission(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:15ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:15ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-j1cd72af58dd67917cd0d6f45c09ebc8410746a5a5fa3ce0f2fc547a0845aa4d6da/debug/pprof/heap — pprof-shape converter on top of /debug/memprof/debug/memprof ships the raw Tarantool memprof binary trace. Open work: a pprof-shape converter — pure-Lua parser for the memprof binary, aggregate events by allocation site, emit a four-dimension perftools.profiles.Profile (alloc_objects/count, alloc_space/bytes, inuse_objects/count, inuse_space/bytes — Go heap profile shape). Implementation sketch: 1. Pure-Lua parser for the memprof binary format (header magic + tagged event stream: alloc / realloc / free / symtab). Reference is tools/memprof.lua + tools/utils/binreader.lua in upstream tarantool/tarantool (not bundled with the homebrew binary). 2. Aggregate into (stack_key → {alloc_objs, alloc_bytes, inuse_objs, inuse_bytes}) with inuse_* from correlating alloc events against later free events inside the same window. Stack keys are the (chunkname, line) chain from symtab events. 3. Encode via lib/protobuf/encoder.lua + lib/pprof/defs.lua — schema already supports multi-sample-type profiles, declare four sample_type entries. 4. New endpoint /debug/pprof/heap?seconds=N on the JSON gateway. Same shape as /debug/pprof/profile (600 s cap, 503 on memprof-unavailable). Existing /debug/memprof stays for raw-trace use cases.Known frictions: - misc.memprof.available == false on Apple Silicon (same arm64 constraint as the JIT — see reference_apple_silicon_no_jit). start() returns true but stop() says "profiler is disabled" and writes nothing. /debug/memprof already detects this and 503s; pprof-heap should do the same. Linux/x86_64 unaffected. - inuse_* is "alive at end-of-window", not "alive right now" — long-lived objects allocated before the window started never appear. Document this; Go heap profile has the same caveat. - Writing the binary parser without ground-truth output is the main risk — develop on a Linux box where memprof actually fires, validate against tools/memprof.lua textual report.1. /debug/pprof/heap?seconds=N returns valid pprof-shaped protobuf, parseable by `go tool pprof`. 2. On Apple Silicon, returns 503 with clear "memprof unavailable on arm64" message. 3. Round-trip tests in test/pprof_test.lua (same shape as the cpu profile tests).Source: docs/TODO.md "Open / Pprof-shape /debug/pprof/heap". Referenced from app/etcd/debug.lua:16, lib/pprof/memprof.lua:12.open3featureNULLNULL2026-05-19T13:34:30ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:30ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-jg3a13319c39a4bdd813b6d85a5f391773719f4b5f9a43692850e00e8bb4928a25cReplica route: config block + role plumbingAdd the role config surface for replica mode and validate/apply it. New block under app.roles.etcd, e.g.: replica: enabled: false mode: mirror # mirror (read-only) | proxy (forward writes) upstream_endpoints: ['http://etcd-a:2379', ...] username: '' # optional auth to upstream password: '' tls: {...} Wire validate/apply/stop in app/roles/etcd.lua: when replica.enabled, the local store must refuse normal write registration and instead start the sync fiber (other child issues). Validate that mode is one of mirror|proxy and endpoints is non-empty. No sync logic here — just config parsing, validation, and the on/off switch the other phases hang off of.Mirrors the existing grpc/json/cmux config block validation in app/roles/etcd.lua.open2taskNULLNULL2026-05-20T06:17:54ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:54ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-kbc3b334f8edc7b7d1335eb359e0d4f364dd8acf1cbb760567eb695a1b7e940b54fConformance test: gRPC Watch on a follower replicatests/conformance/replicaset_smoke_test.go covers ReadReplicatesToFollowers (Range on each follower after a leader Put) but nothing exercises a Watch stream *pinned to a follower endpoint* while mutations happen on the leader. The Lua integration test (test/grpc_integration_test.lua:547) explicitly punts: "True replicaset behaviors (watch deliveries across nodes ...) need a real Raft cluster and live in the Go harness." Watch on a follower has its own moving parts that Range does not: - the watcher fiber lives on the follower - kv_history rows arrive via replication (relay → applier), not via the local mutation - the box.on_commit broadcast must fire on the applier path (see memory feedback_tarantool_trigger_broadcast — broadcast from on_commit, not on_replace, so the woken reader sees committed state on the follower side too) Without this test, a regression in the follower-side watch wake-up would slip through the rs3 suite.- Reuse mustDial(t, []string{followerEndpoint}) from existing rs3 tests — same dial pattern as ReadReplicatesToFollowers. - Use a short context.WithTimeout (5 s wall, 2 s wait-for-event) — replication lag on the local rs3 harness is sub-ms. - Use harness.UniqueKey(t) for key isolation. - Skip on non-rs3 backend (the single-node tarantool backend has no follower). - Mirror the synchronous "wait for created chunk" pattern jsonclient/watch already uses, even on the gRPC client — avoids the race where the Put commits before the Watch is registered.1. New test in tests/conformance/replicaset_smoke_test.go that: a. Spawns the rs3 backend, identifies leader + followers via rs.LeaderEndpoint / rs.Endpoints. b. Opens a Watch stream pinned to each follower endpoint (one subtest per follower). c. Issues a Put on the leader. d. Asserts the follower-side watcher receives the PUT event within a short deadline (≤2 s on a quiet box). e. Asserts the event header.revision matches the leader-side Put response revision. 2. Additional subtest: range watch ("/rs_smoke/watch/", "\0") on a follower receives multiple events in revision order when the leader issues several Puts. 3. Optional subtest: prev_kv populated correctly on the follower-side event when WithPrevKV is requested. 4. Suite stays green with CONFORMANCE_BACKEND=tarantool_rs3 go test -count=1 -run TestReplicasetSmoke -v.Source: gap surfaced while porting docs/TODO.md to bd on 2026-05-19. Cross-refs: tests/conformance/replicaset_smoke_test.go ReadReplicatesToFollowers (line ~160), test/grpc_integration_test.lua:547 comment about which behaviors live where, memory feedback_tarantool_trigger_broadcast.open2taskNULLNULL2026-05-19T14:11:02ZEugene Blikhbigbes@gmail.com2026-05-19T14:11:02ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-lac9b0811dbe3090da92e2f2c059b263cbef43e1721b4418917747dcf3102a20f60Phase 5e — Lease option coveragePer-option density on Lease RPCs. Canonical paths are already covered; what is missing is option coverage in the {tarantool, etcd} × {grpc, json} matrix. Smallest remaining surface — should be the warm-up before Phase 5f. Likely tests: - TestLeaseGrantWithExplicitID - TestLeaseGrantTTLBoundaries (TTL=0 / negative / very-large) - TestLeaseTimeToLiveAttachedKeys - TestLeaseRevokeRevokesAttachedKeys (each attached key disappears + watcher sees DELETE at the revoke revision) - TestLeaseKeepAliveOnceTTLZero (cross-wire — jsonclient-internal case already pinned) Sub-phases 5a-c each surfaced one Lua-side divergence — expect at least one more here.Each listed test ported, runs on all four cells, passes (or is documented as a known gap in tests/conformance/harness/gaps.go cross-referenced from docs/TODO.md).Source: docs/TODO.md "Open / Conformance matrix — Phase 5 option coverage".open2taskNULLNULL2026-05-19T13:34:01ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:01ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-lkoa9f5b3fdb1d8c955ea9817c5961cd2fd334733f9495cfcea8dc728d5d59c5badRoute writes to current master (write-forwarding on followers)Followers currently reject writes with ER_READONLY → gRPC UNAVAILABLE, and clientv3 does NOT fail over endpoints on Unavailable (see memory feedback_clientv3_error_assertions). Clients must pin to the leader, which breaks endpoint-agnostic client setups (AutoSyncInterval, DNS round-robin, k8s Service). Implement write-forwarding inside the role: when a follower receives a mutating RPC (Put / DeleteRange / Txn-with-writes / LeaseGrant / LeaseRevoke / LeaseKeepAlive / Compact / Auth* / Lock / Campaign / Resign / Proclaim), proxy it to the current Raft leader via experimental.connpool + a setuid stored Lua function (same pattern as MaintenanceMoveLeader, see project_cross_node_promote memory). Reads stay local per replicaset.read_pref (already implemented).- Reuse the connpool helper introduced for MaintenanceMoveLeader (tests/conformance/harness/tarantool_rs_server.go:475 area). - Trigger forwarding inside grpc.lua make_handler before dispatching the write — cheaper than wrapping every kv/lease/txn module. - box.info.election.leader gives the leader id; map id→advertise URL via advertise.lua (already used for MemberList clientURLs). - Streaming RPCs (Watch, LeaseKeepAlive, Election Observe) are subtler — defer or handle separately; first cut should be unary-only.1. Mutating RPC on a follower in tarantool_rs3 backend succeeds (matches the leader-equivalent response shape, including header.revision monotonicity). 2. No regression in existing rs3 conformance subtests. 3. New conformance subtest TestWriteForwardingOnFollower covers Put/Txn/LeaseGrant from a follower endpoint. 4. If the leader is unknown (election in progress), return ErrGRPCNoLeader as today.Discussed in chat 2026-05-19 as the only multi-master option that preserves etcd contract. Memory refs: project_cross_node_promote, feedback_clientv3_error_assertions.open2featureNULLNULL2026-05-19T13:33:55ZEugene Blikhbigbes@gmail.com2026-05-19T13:33:55ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-m0w1e497e0d597a35ddd55d2b06dbb53bee3d2af9ede56d5397f2267151a481b309iproto-verify: etcd_unlock vs Lock.UnlockAdd Lua testkit verification for etcd_unlock (mirrors gRPC Lock.Unlock). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/lock. Call shape: local resp = etcd_unlock(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:18ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:18ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-m1nc9126753270e756137235fe87d06b79c038f9607c12502bc9e772f6f2ff6cf6ciproto-impl: etcd_election_leader vs Election.LeaderWrap the existing handler election.leader (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Leader) as a Lua global etcd_election_leader callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_leader', wrap('election', 'leader')) under the appropriate service block; append 'etcd_election_leader' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Election.Leader returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_election_leader is callable from net.box:call('etcd_election_leader', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/election.lua.open3taskNULLNULL2026-05-19T14:54:48ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:48ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-mo5dbe7e65616d159fdbd81f97f8b988209daa63549799f00a9436da023cecace05iproto-verify: etcd_member_list vs Cluster.MemberListAdd Lua testkit verification for etcd_member_list (mirrors gRPC etcdserverpb.Cluster.MemberList). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/cluster.Epic tarantool-etcd-w8q. Blocked on the matching impl issue.open3taskNULLNULL2026-05-19T14:54:26ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:26ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ns020b6fc12f33291102415f4213204ede198952347fae1b7e670b587ba2f267a73iproto-verify: etcd_maintenance_defragment vs Maintenance.DefragmentAdd Lua testkit verification for etcd_maintenance_defragment (mirrors gRPC etcdserverpb.Maintenance.Defragment). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/maintenance.Epic tarantool-etcd-w8q. Blocked on the matching impl issue.open3taskNULLNULL2026-05-19T14:54:35ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:35ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-nwl3f54509527d06071750dbdddfdcafe415133385b9549ce08b80b06cc16f9d6cfiproto-verify: etcd_user_revoke_role vs Auth.UserRevokeRoleAdd Lua testkit verification for etcd_user_revoke_role (mirrors gRPC Auth.UserRevokeRole). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_user_revoke_role(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:11ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:11ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ovtdb6cf24009cca490a9e5a89f705f27d73388ddfcc3513448452e373522faeeb5iproto-verify: etcd_member_remove vs Cluster.MemberRemoveAdd Lua testkit verification for etcd_member_remove (mirrors gRPC etcdserverpb.Cluster.MemberRemove). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/cluster.Epic tarantool-etcd-w8q. Blocked on the matching impl issue.open3taskNULLNULL2026-05-19T14:54:21ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:21ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ozm88152e03bc9011e822aa42ffc9212e11e04a9788bd5d40d5312f3e47da59657ciproto-verify: etcd_user_list vs Auth.UserListAdd Lua testkit verification for etcd_user_list (mirrors gRPC Auth.UserList). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_user_list(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:09ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:09ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-p3sd7ab326ea50217052ff7528067d9bda449d1d177009210c5b6dc67df52f33a52iproto-verify: etcd_election_leader vs Election.LeaderAdd Lua testkit verification for etcd_election_leader (mirrors gRPC v3electionpb.Election.Leader). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/election.Epic tarantool-etcd-w8q. Blocked on the matching impl issue.open3taskNULLNULL2026-05-19T14:54:48ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:48ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-rzh26beb784e16ef7c22030f27a08fe4e55b5e0453b6cd19af9df1ffd97a8bb3235iproto-impl: etcd_maintenance_status vs Maintenance.StatusWrap the existing handler maintenance.status (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.Status) as a Lua global etcd_maintenance_status callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_status', wrap('maintenance', 'status')) under the appropriate service block; append 'etcd_maintenance_status' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Maintenance.Status returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_maintenance_status is callable from net.box:call('etcd_maintenance_status', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/maintenance.lua.open3taskNULLNULL2026-05-19T14:54:32ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:32ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-rzr3973dcbaf27d8ffaf25bdad2afcfcbfeb9e6deb07cd8ecf62c5a6446247c3468nghttp2 unary send-path rewrite — close parallel KVGet gap, drop jit.offParallel KVGet on tarantool is ~70% slower than etcd at GOMAXPROCS=6 (12 688 ops/s vs 21 900 ops/s; p95 970 µs vs 405 µs — docs/BENCH.md "Linux x86_64 — KVGet matrix, 2026-05-15"). Root cause: per-Connection IO mutex in lib/nghttp2/grpc.lua (Connection:_locked) — nghttp2 sessions are not reentrant, so every fiber's submit_response + send_all + sock:write serializes. Etcd has no such constraint. Fix: pre-build HEADERS + DATA + trailers in pure Lua, skip nghttp2's C→Lua data-source callback on the unary send path, recover ~10–20% throughput lost to jit.off + drop the JIT pin entirely.See memory project_nghttp2_send_callback_rewrite for the plan. Pre-frame DATA in Lua, avoid re-entering nghttp2 mid-send. Touch points: - lib/nghttp2/grpc.lua (Connection, _locked, send_response) - lib/nghttp2/ffi.lua (data-source callback signature) - M.recv/M.send/M.send_all/M.send_data currently pinned jit.off — un-pin once the callback re-entry is gone (memory feedback_nghttp2_session_not_reentrant explains the original panic).1. BenchmarkKVGetParallel/point closes the gap to within ~10% of etcd at GOMAXPROCS=6. 2. p95 latency under parallel load drops below 600 µs. 3. No bad-callback panics across 10 verbose runs (the regression test from commit d0fa396). 4. jit.off removed from M.recv/M.send/M.send_all/M.send_data.Sources: docs/BENCH.md "Linux x86_64" + memory notes project_nghttp2_send_callback_rewrite, feedback_nghttp2_session_not_reentrant, feedback_nghttp2_dual_connection.open2taskNULLNULL2026-05-19T13:34:42ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:42ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-rzs63c2e0e3f3c883b2db5734e851457a1f568e3a1ebb871de515f13411bd7ecbd9iproto-impl: etcd_member_update vs Cluster.MemberUpdateWrap the existing handler cluster.member_update (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberUpdate) as a Lua global etcd_member_update callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_update', wrap('cluster', 'member_update')) under the appropriate service block; append 'etcd_member_update' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Cluster.MemberUpdate returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_member_update is callable from net.box:call('etcd_member_update', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/cluster.lua.open3taskNULLNULL2026-05-19T14:54:23ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:23ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-sdtce9fb24507b45a493bd9ffc4a4ab22edafe46b9e41a95b2813bb6b2016b0ccc8iproto-verify: etcd_auth_status vs Auth.AuthStatusAdd Lua testkit verification for etcd_auth_status (mirrors gRPC Auth.AuthStatus). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_auth_status(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:04ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:04ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-sqve03dd24141b120acf0cc989ed396918ed61284c9962f1c036f30a262a51d39e6iproto-impl: etcd_election_proclaim vs Election.ProclaimWrap the existing handler election.proclaim (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Proclaim) as a Lua global etcd_election_proclaim callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_proclaim', wrap('election', 'proclaim')) under the appropriate service block; append 'etcd_election_proclaim' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Election.Proclaim returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_election_proclaim is callable from net.box:call('etcd_election_proclaim', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/election.lua.open3taskNULLNULL2026-05-19T14:54:46ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:46ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-sy6ff088cd8c36175c942b8e80aa7a1bfa3bdaa64bf92a9ff46f8c736505ea0b302iproto-verify: etcd_watch_pull vs Watch.Watch-pullAdd Lua testkit verification for etcd_watch_pull (mirrors gRPC Watch.Watch-pull). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/watch. Call shape: local resp = etcd_watch_pull(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:57ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:57ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-tf04410402a2773378d989b3453c6d566e9ab0eb85ec6a8ba9eb21801b478e96d73iproto-impl: etcd_maintenance_hash_kv vs Maintenance.HashKVWrap the existing handler maintenance.hash_kv (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.HashKV) as a Lua global etcd_maintenance_hash_kv callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_hash_kv', wrap('maintenance', 'hash_kv')) under the appropriate service block; append 'etcd_maintenance_hash_kv' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Maintenance.HashKV returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_maintenance_hash_kv is callable from net.box:call('etcd_maintenance_hash_kv', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/maintenance.lua.open3taskNULLNULL2026-05-19T14:54:39ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:39ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-tt663510fbc9abb4568f1a181ec6515e1edededff7dbb3a0cf8e1f67e62b24c780dReplica route: lease / auth state mirroring (scope v1 vs later)KV is the v1 target; this issue scopes how non-KV state behaves in replica mode and what (if anything) v1 mirrors. Questions: - Leases: do we mirror upstream lease grants/TTLs/expiry so locally-served keys show correct lease attachment, or pass-through lease ops to upstream? At minimum the lease_id on replicated kvs must round-trip; full lease lifecycle mirroring may be later. - Auth: mirror upstream users/roles/permissions, or run replica reads unauthenticated/locally-authed? Decide whether auth is enforced on the replica or delegated. - Watch served to local clients: our Watch subsystem already reconstructs from kv_history, which the tail populates — confirm local watchers work transparently once KV sync lands. Output: a documented v1 scope (likely 'KV + lease_id round-trip only; auth+full-lease+ deferred') appended to docs/TODO.md, plus any follow-up issues.Likely mostly a scoping/decision issue that spawns concrete follow-ups; keep v1 KV-only.open2taskNULLNULL2026-05-20T06:17:57ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:57ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-uee9e6ca4342149c79eee16a063f881ae3eb1683b9de5774eae58d2b37bfc8bcb9bReplica route: bootstrap snapshot importOn entering replica mode, pull the full upstream keyspace once and load it into our etcd_* spaces, recording the upstream revision the snapshot was taken at (the Watch tail starts from here). Approach: a clientv3-style Range over the whole keyspace ([\\x00, \\x00) with WithRange/WithFromKey) reading at a single revision (use the header.revision from the first Range, or RangeRequest with revision pinned + paging via WithLimit + WithMinModRev/last-key continuation). Persist each kv with its create_revision/mod_revision/version/lease intact. Alternatively consume Maintenance.Snapshot if/when interop lands (tarantool-etcd-16d) — but Range is the dependency-free path for v1. Output: etcd_* spaces populated, and the 'synced through revision R' watermark persisted for the tail phase to resume from.Must preserve upstream create_revision/mod_revision/version exactly — feeds revision-alignment. Page large keyspaces to avoid one giant Range.open2taskNULLNULL2026-05-20T06:17:54ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:54ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-w5r3a127352109f5847f90475b493f71b010fa77a962ab2ab7fd469ed01e25e9984iproto-impl: etcd_election_campaign vs Election.CampaignWrap the existing handler election.campaign (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Campaign) as a Lua global etcd_election_campaign callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_campaign', wrap('election', 'campaign')) under the appropriate service block; append 'etcd_election_campaign' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Election.Campaign returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_election_campaign is callable from net.box:call('etcd_election_campaign', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/election.lua.open3taskNULLNULL2026-05-19T14:54:43ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:43ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-w6za1dfa11cf641fccae10ce051a21c5eaca457020ec09cb52c85f4e5cc8d0062c1iproto-verify: etcd_election_campaign vs Election.CampaignAdd Lua testkit verification for etcd_election_campaign (mirrors gRPC v3electionpb.Election.Campaign). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/election.Epic tarantool-etcd-w8q. Blocked on the matching impl issue.open3taskNULLNULL2026-05-19T14:54:44ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:44ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-w8q472222f8e9e50041b82f23593de29308c6f31d0649b21012f82ea3df9f38020ciproto parity for the gRPC surfaceBring app/etcd/api.lua iproto CALL surface to functional parity with the gRPC surface in app/etcd/pb/defs.lua. 32 already-implemented endpoints need Lua verification tests; 16 missing endpoints (Cluster, Maintenance, Election) need both implementation wrappers and tests. Out of scope: Watch and LeaseKeepAlive bidi-streams, Maintenance.Snapshot/Downgrade. For UNIMPLEMENTED-by-design endpoints, wrappers are created anyway and propagate the same UNIMPLEMENTED error so the surface is uniform.Every gRPC method in defs.lua (excluding streaming divergences) has a matching etcd_* iproto wrapper. Every wrapper has a Lua testkit test in test/iproto_parity_test.lua asserting response shape and error mapping match gRPC. test/run.lua group iproto/parity passes.open2epicNULLNULL2026-05-19T14:53:51ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:51ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-wgx5a455111b3144aca15dfc7df9cce92515e6000d9cd0fa1e761c4ba493c83082fiproto-verify: etcd_authenticate vs Auth.AuthenticateAdd Lua testkit verification for etcd_authenticate (mirrors gRPC Auth.Authenticate). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_authenticate(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:05ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:05ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-wqna7a2759a10e1b49b4c98ebf2bcc0979aff638f3764809fdee4605d8441e1adb6iproto-impl: etcd_maintenance_alarm vs Maintenance.AlarmWrap the existing handler maintenance.alarm (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.Alarm) as a Lua global etcd_maintenance_alarm callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_alarm', wrap('maintenance', 'alarm')) under the appropriate service block; append 'etcd_maintenance_alarm' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Maintenance.Alarm returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_maintenance_alarm is callable from net.box:call('etcd_maintenance_alarm', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/maintenance.lua.open3taskNULLNULL2026-05-19T14:54:30ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:30ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ymm5abccb539c482913cabd242acf2b32afd6eb182fda57781a502ac4411d704a0diproto-impl: etcd_maintenance_move_leader vs Maintenance.MoveLeaderWrap the existing handler maintenance.move_leader (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.MoveLeader) as a Lua global etcd_maintenance_move_leader callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_move_leader', wrap('maintenance', 'move_leader')) under the appropriate service block; append 'etcd_maintenance_move_leader' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Maintenance.MoveLeader returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_maintenance_move_leader is callable from net.box:call('etcd_maintenance_move_leader', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/maintenance.lua.open3taskNULLNULL2026-05-19T14:54:41ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:41ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-zwg5f1f8ad7dadfa6be0ecaa0dc1d71f690076e930bc5073feb538b71faf1f2d7d6iproto-verify: etcd_user_get vs Auth.UserGetAdd Lua testkit verification for etcd_user_get (mirrors gRPC Auth.UserGet). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_user_get(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:08ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:08ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-zwsb99aec7b0025f26f4e59b5bf3e6287ee00f117d8f119775c13dcfbb23132d00eReplica route: revision alignment with upstreamIn replica mode the local global revision sequence (box.sequence in revision.lua) must mirror upstream's revisions exactly so that Range/Watch reads return etcd-consistent create_revision/mod_revision/header.revision. Work: - While replica mode is active, the local revision allocator must NOT mint its own revisions for replicated writes; it must set revision = the upstream mod_revision carried by each Range/Watch event. - Decide handling of the box.sequence: drive it to upstream's current revision (set, not next()) as events apply, or bypass it entirely for replicated mutations via the *_internal write paths. - Ensure header.revision returned to local clients equals the latest synced upstream revision, and compact_revision tracks upstream compaction. This is cross-cutting with bootstrap + watch-tail; it defines the invariant both must uphold.revision.lua owns the box.sequence. Replicated writes likely go through put_internal/delete_range_internal with an explicit revision arg to avoid double-allocation.open2taskNULLNULL2026-05-20T06:17:55ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:55ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL