~bigbes/tarantool-etcd · issues

dnvp9n5cdao2413gsdhm6fe7ar9vo7on · 78 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-0706acbf4a75e199fd9fc37cbfa4584a578ca4024d8454ea401c97fac60b9ba7614iproto-verify: etcd_watch_cancel vs Watch.Watch-cancelAdd Lua testkit verification for etcd_watch_cancel (mirrors gRPC Watch.Watch-cancel). 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_cancel(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:58ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:58ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-0gvb9d3c59f8e7df072d263e07416056e3b25b412b9f8d2c1c1bbcffd1d0ca91810iproto-verify: etcd_user_change_password vs Auth.UserChangePasswordAdd Lua testkit verification for etcd_user_change_password (mirrors gRPC Auth.UserChangePassword). 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_change_password(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:10ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:10ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-0usbc2b961d826c01422901d943b0a374e659925e4a505a60526acd56b5c0a13babiproto-verify: etcd_maintenance_status vs Maintenance.StatusAdd Lua testkit verification for etcd_maintenance_status (mirrors gRPC etcdserverpb.Maintenance.Status). 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:33ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:33ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-0uw0d8c71e8a752102df90c233ba610d1de22ea1a0f26c7ca03acdfc64a64b9f649iproto-verify: etcd_txn vs KV.TxnAdd Lua testkit verification for etcd_txn (mirrors gRPC KV.Txn). 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/kv. Call shape: local resp = etcd_txn(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:54ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:54ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-16dc3ed04edeb2dc3f191d8cd287f502242a4fe98be2442a5343e1a416695f6572aImplement Maintenance.Snapshot RPC (streaming DB snapshot)The etcd v3 Maintenance.Snapshot RPC streams a full backend snapshot to the client (server-streaming: SnapshotResponse chunks carry remaining_bytes, blob, and a trailing SHA256 hash; etcdctl/clientv3 reassemble into a bolt .db file). Today it is deliberately stubbed: json.lua:13 documents /v3/maintenance/snapshot as 501, and there is no handler in maintenance.lua nor a routes entry in defs.lua (Maintenance methods top out at MoveLeader [5]). What's needed: - Decide what a 'snapshot' means for a Tarantool-backed store. Real etcd ships a bolt DB; we'd need to either (a) produce an etcd-compatible bolt snapshot the upstream tooling can restore, or (b) define our own snapshot format (likely a box snapshot / dump of the etcd_* spaces + revision sequence) and document the divergence. (a) is a large undertaking; (b) is the pragmatic path but breaks 'etcdctl snapshot restore' interop. - Wire the server-streaming method: add SnapshotRequest/SnapshotResponse schemas to defs.lua, a routes entry, a streaming handler in maintenance.lua, and stream support on both wires (gRPC HTTP/2 + JSON gateway chunked). - Emit remaining_bytes + blob chunks + final hash per the etcd contract. Document the chosen approach + any divergence in docs/TODO.md and (if it can't fully pass conformance) add to harness/gaps.go.Cross-wire streaming: gRPC server-streaming + JSON gateway chunked POST. Mirror existing streaming patterns (Watch). Acceptance: etcdctl snapshot save succeeds against our server, OR documented divergence if we ship a non-bolt format.open2featureNULLNULL2026-05-20T05:47:59ZEugene Blikhbigbes@gmail.com2026-05-20T05:47:59ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-21628369b3161fd83e9748fd8cd2732132d9fb63d890439e3733282f22dfc57b524iproto-verify: etcd_maintenance_hash vs Maintenance.HashAdd Lua testkit verification for etcd_maintenance_hash (mirrors gRPC etcdserverpb.Maintenance.Hash). 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:37ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:37ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-2346a864d040222a5c7b7ec4e61daed84bfd693cc407841df0f2101755949bfd026LeaseGrantRevoke perf regression — revalidate before chasingLeaseGrantRevoke regressed from 2 243 ops/s to 1 223 ops/s against the previous bench baseline (docs/BENCH.md "Refresh — 2026-05-14, post select+count Range fast path", section "Known issues — open"). Bench code on this leaf is unchanged; revalidate with a second run before chasing the cause — bench noise on this leaf is plausible.1. Re-run BenchmarkLeaseGrantRevoke on the same hardware (Apple M4 Pro per BENCH.md), 5 s/leaf, fresh subprocess per leaf. 2. If still ~1 223 ops/s, bisect across the commits between the 2 243 and 1 223 measurements (git log between BENCH.md baselines). 3. If back at ~2 243, close as noise.Source: docs/BENCH.md section "Known issues — open" near line 244.open3bugNULLNULL2026-05-19T13:34:48ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:48ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-2al5f1b8211e76acdf580cf1191135c8a84be0bfb1453bf403bd5b92027addf4dbfiproto-verify: etcd_user_grant_role vs Auth.UserGrantRoleAdd Lua testkit verification for etcd_user_grant_role (mirrors gRPC Auth.UserGrantRole). 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_grant_role(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:10ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:10ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-2pa898453b613dd144bd8b1f5db13f2cefd2835dd7aea0af008be3f485229f5f9e1iproto-verify: etcd_role_delete vs Auth.RoleDeleteAdd Lua testkit verification for etcd_role_delete (mirrors gRPC Auth.RoleDelete). 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_delete(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:13ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:13ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-3c21b24f6a27bf95dcbb79ff9d253fcaff82918a95ecf2d9d694cb3f41471f944d8iproto-verify: etcd_member_update vs Cluster.MemberUpdateAdd Lua testkit verification for etcd_member_update (mirrors gRPC etcdserverpb.Cluster.MemberUpdate). 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:24ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:24ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-3coa4e494d731f91d11cb4d3d65e1578c1cd2f5b09229e3f00bd1dc036e36ee209biproto-verify: etcd_role_revoke_permission vs Auth.RoleRevokePermissionAdd Lua testkit verification for etcd_role_revoke_permission (mirrors gRPC Auth.RoleRevokePermission). 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_revoke_permission(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:16ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:16ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-3dkf26e1791677ec8877ef162eeaf8e523b01b1fea8528cb4a62fd6ac2867bba7e8iproto-verify: etcd_compact vs KV.CompactAdd Lua testkit verification for etcd_compact (mirrors gRPC KV.Compact). 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/kv. Call shape: local resp = etcd_compact(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:55ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:55ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-3spb038f07d4b3a4fd5ba29a64bcd636f80cd4570e04433691e65570a2861e978ecLeaseKeepAlive fsyncs WAL on every renewOn btrfs SSD bench (2026-05-19 disk run), LeaseKeepAlive/n_X drops from 4 234 ops/s (tmpfs) to 207 ops/s on tarantool while etcd holds at ~7 400 ops/s in both configs. p50 goes from 224 µs (tmpfs) to 4 548 µs (disk) — exactly one btrfs fsync. Root cause at app/etcd/lease.lua:191: box.space.leases:update(id, {{'=', 'expiry_time', now + lease.ttl}}) The leases space is is_sync=true so every keep-alive does a full WAL append + fsync. Etcd's KeepAlive is an in-memory TTL bump with no disk write. Fix sketch: split expiry into an in-memory map (refreshed on every KeepAlive) and persist only on grant/revoke. The expiry fiber should read from the in-memory map. Trade-off: leases may extend further into the future than the on-disk record after a crash, which is fine — clients have to re-keep-alive after reconnect anyway. See docs/BENCH.md Linux x86_64 disk section (Open follow-ups).GOAL: lease keep-alive must not touch the WAL. Mirror etcd's split — durable state = {lease record, granted TTL, attached keys}; ephemeral leader-local state = the expiry deadline (refreshed on every keep-alive, never persisted). === STATE MODEL === Add a module-level in-memory map in app/etcd/lease.lua: local deadlines = {} -- [lease_id] = monotonic deadline (clock.monotonic()+ttl) This is leader-local. Followers never keep-alive (the gRPC write gate routes LeaseKeepAlive to the leader), and only the leader runs the expiry fiber and can revoke. So the countdown is structurally a leader concern. The `leases` space (schema.lua:97-118) stays is_sync=true and keeps its {id, ttl, expiry_time, granted_ttl} format. The `expiry_time` FIELD and its TREE index (schema.lua:113) become vestigial — written once at grant, never the source of liveness again. Leave them to avoid a space migration; an optional follow-up can drop the field+index. Nothing reads expiry_time after this change. === HANDLER CHANGES (app/etcd/lease.lua) === 1. grant() ~L70: after `box.space.leases:insert(...)`, seed `deadlines[id] = now + ttl`. Insert still persists (durable, required). 2. keepalive() ~L191: REPLACE box.space.leases:update(id, {{'=', 'expiry_time', now + lease.ttl}}) with deadlines[id] = clock.monotonic() + lease.ttl Keep the `box.space.leases:get(id)` existence check above it (cheap read, no fsync) — it supplies lease.ttl and preserves the NOT_FOUND-raises contract the gRPC stream handler depends on (see L169-171). 3. revoke() ~L150: after `box.space.leases:delete(id)`, clear `deadlines[id] = nil`. 4. time_to_live() ~L236: REPLACE `lease.expiry_time` read with `deadlines[id]`. If deadlines[id] is nil (lease loaded but not yet rebuilt), fall back to `clock.monotonic() + lease.granted_ttl`. remaining = max(0, floor(dl - now)). 5. expiry_loop() L287-338: REPLACE the `box.space.leases.index.expiry_time` scan (L302-309) with a scan of `deadlines`: collect ids where `deadline <= now`. Plain full-table scan is fine (numeric compares in Lua, runs every 500ms); a min-heap (etcd's leaseExpiredNotifier shape) is the optional optimization if lease counts get large. revoke() already nils the map entry on success. === REBUILD ON PROMOTE === Add lease.M.rebuild_deadlines(): clears `deadlines`, then for each tuple in box.space.leases:pairs() sets deadlines[tuple.id] = clock.monotonic() + tuple.ttl Call it in the RW branch of the box.watch('box.status', ...) callback in app/roles/etcd.lua (L341-353), immediately before lease.start_expiry(). This resets every inherited lease's deadline to a full-TTL grace period on the new leader — exactly etcd's failover behavior. === LATENT BUG THIS ALSO FIXES === expiry_time is currently computed as clock.monotonic()+ttl and REPLICATED. clock.monotonic() is process-local (relative to boot), so the persisted value is meaningless on any other node. Today a promoted replica's fiber scans inherited expiry_time values from a different monotonic timeline — could expire leases instantly or never. Rebuild-on-promote with the new leader's own clock removes this entirely.- keepalive issues ZERO WAL writes: box.info.lsn delta == 0 across N successive M.keepalive() calls on the same lease. - BenchmarkLeaseKeepAlive/n_* on btrfs SSD (work.lab.local, real-disk run) recovers from 207 ops/s to within ~2x of etcd (~4000+ ops/s, near the tmpfs baseline). Re-run: TMPDIR=$HOME/bench-data go test -run=^$ \ -bench=^BenchmarkLeaseKeepAlive$ -benchtime=5s ./bench/ - Lease still expires correctly: grant short TTL, no keep-alive, attached keys are deleted by the fiber after TTL elapses; keep-alive before TTL prevents it. - TimeToLive reflects the latest keep-alive (remaining resets to ~ttl after a renew). - Promote rebuilds deadlines: a freshly-promoted leader expires inherited leases using its own monotonic clock (no instant-expiry, no never-expiry). - All existing lease conformance cells (tarantool, tarantool_json, tarantool_rs3) and Lua lease tests pass.TESTS (add Lua-side tests pinning the fix per the project's regression rule): - no-WAL: assert box.info.lsn unchanged across keepalive calls. - liveness: keepalive refreshes deadline (TimeToLive resets, lease survives). - promote rebuild: use the box.cfg{read_only=true}...{read_only=false}+ box.ctl.promote() in-process follower-simulation pattern (see role_test.lua group role/write_gates_in_process) to verify rebuild_deadlines repopulates. - cross-node: optionally exercise via the replicaset harness that a promoted replica expires an inherited lease. Conformance already covers cross-wire correctness; this is about the Lua unit pins + the bench recovery number. DOCS: update docs/BENCH.md Linux x86_64 disk section once re-benched; remove the LeaseKeepAlive "bug" annotation from the headline table. SCOPE NOTE: leave the expiry_time field + index in place (no migration). Only the keepalive write path and the fiber's liveness source change.open2bugNULLNULL2026-05-19T17:33:47ZEugene Blikhbigbes@gmail.com2026-05-20T04:39:23ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-40sead9d8881e362dcd5ca4281953373c9694eda30e348db3ecc62fd3c38305316biproto-verify: etcd_lease_leases vs Lease.LeaseLeasesAdd Lua testkit verification for etcd_lease_leases (mirrors gRPC Lease.LeaseLeases). 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/lease. Call shape: local resp = etcd_lease_leases(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:02ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:02ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-4nr54ecc2a70763771b850026ebc04dd6a36b3c0fdb078a641e138d98b3c334dbaaiproto-impl: etcd_maintenance_defragment vs Maintenance.DefragmentWrap the existing handler maintenance.defragment (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.Defragment) as a Lua global etcd_maintenance_defragment callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_defragment', wrap('maintenance', 'defragment')) under the appropriate service block; append 'etcd_maintenance_defragment' 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.Defragment 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_defragment is callable from net.box:call('etcd_maintenance_defragment', {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:34ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:34ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-4y9f06c275959d16e0105fc6079ad51b3fc76f4073f72e0025384ebedc3ddc01161iproto-impl: etcd_election_resign vs Election.ResignWrap the existing handler election.resign (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Resign) as a Lua global etcd_election_resign callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_resign', wrap('election', 'resign')) under the appropriate service block; append 'etcd_election_resign' 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.Resign 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_resign is callable from net.box:call('etcd_election_resign', {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:52ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:52ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-50g9ac78e7144a952bc4f60bc5066817e0c5fc22a141911d263cb1dcbf71563381diproto-verify: etcd_member_add vs Cluster.MemberAddAdd Lua testkit verification for etcd_member_add (mirrors gRPC etcdserverpb.Cluster.MemberAdd). 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:19ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:19ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-5846dc9ac8fa6d51da02d14d688bcfb11d64010ca9fd1c2d4497a9ebcca4fc713a9iproto-verify: etcd_delete_range vs KV.DeleteRangeAdd Lua testkit verification for etcd_delete_range (mirrors gRPC KV.DeleteRange). 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/kv. Call shape: local resp = etcd_delete_range(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:54ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:54ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-5zx89ee417ec71ddfded73ee7497c3e7938ddf799b0994f05df2b0d46281d429ce6iproto-impl: etcd_maintenance_hash vs Maintenance.HashWrap the existing handler maintenance.hash (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.Hash) as a Lua global etcd_maintenance_hash callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_hash', wrap('maintenance', 'hash')) under the appropriate service block; append 'etcd_maintenance_hash' 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.Hash 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 is callable from net.box:call('etcd_maintenance_hash', {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:37ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:37ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-60xb21cef8f1637e804633f1c652b78bb5b4424883973d65867bc58080466b810e5iproto-verify: etcd_lease_timetolive vs Lease.LeaseTimeToLiveAdd Lua testkit verification for etcd_lease_timetolive (mirrors gRPC Lease.LeaseTimeToLive). 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/lease. Call shape: local resp = etcd_lease_timetolive(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:01ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:01ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-6ljd4341bb5465f48998fc359076cde70c55d1e60ea8e549e16b8e29211154a84b3iproto-verify: etcd_watch_create vs Watch.Watch-createAdd Lua testkit verification for etcd_watch_create (mirrors gRPC Watch.Watch-create). 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_create(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:56ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:56ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-70j7fc065ea5ee00fb1ca4be14474b96cab64a446406a541f3874fd9adff86e3279iproto-verify: etcd_member_promote vs Cluster.MemberPromoteAdd Lua testkit verification for etcd_member_promote (mirrors gRPC etcdserverpb.Cluster.MemberPromote). 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:28ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:28ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-7eybe7b04f2cbf862eb22cfe43df8812d0bcb20c7b247f8edc485850c3fb44cbe34Replica route: connect as read-only replica to an existing etcd clusterAdd a mode where this server attaches to an existing/real etcd cluster as a read-only replica (mirror), serving reads locally while transparently keeping in sync with the upstream etcd. Motivation: lets the Tarantool store act as a read scale-out / local cache in front of a real etcd deployment, and is a stepping stone toward migration (shadow the production cluster, compare, then cut over). Design questions to resolve: - Sync mechanism: use etcd's Watch (clientv3) from revision 0 to stream the full keyspace + tail live, persisting events into our etcd_* spaces and advancing our revision counter to match upstream. Need an initial Range snapshot (or Snapshot RPC) for bootstrap, then Watch with progress notifications + compaction handling (ErrCompacted -> re-snapshot). - Revision alignment: our global revision sequence must track upstream's mod_revision exactly so reads return etcd-consistent revisions. This constrains the local revision allocator while in replica mode. - Write handling: reject writes locally with a redirect/error, OR proxy them to the upstream leader and wait for the change to come back over the watch (read-your-writes). Pick one; proxying is closer to etcd's learner/proxy semantics. - Lease/Watch/Auth: leases and auth state also need mirroring or pass-through. Scope what's in v1 (KV-only read replica) vs later. - Config: new role config block (e.g. replica.upstream_endpoints, replica.mode = mirror|proxy, credentials). Likely a multi-phase epic; this ticket captures the umbrella. Split bootstrap-snapshot, watch-tail-sync, revision-alignment, and write-proxying into child issues once the design is settled.Reuses clientv3 Watch semantics we already understand from conformance work (ErrCompacted=11, progress notify). Consider relation to the Tarantool-native replicaset path (tarantool_rs3) — this is the opposite direction (follow a foreign etcd, not our own Raft).open2featureNULLNULL2026-05-20T05:48:15ZEugene Blikhbigbes@gmail.com2026-05-20T05:48:15ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-7kb85033a35f894073794d9015ec94b0b8854abfbcee2245a2eb1683814a67c68c3iproto-impl: etcd_member_add vs Cluster.MemberAddWrap the existing handler cluster.member_add (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberAdd) as a Lua global etcd_member_add callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_add', wrap('cluster', 'member_add')) under the appropriate service block; append 'etcd_member_add' 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.MemberAdd 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_add is callable from net.box:call('etcd_member_add', {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:19ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:19ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-82807dec43fc47708505ca97b18aaf13e621ccca512a7a74fe5c56e9fc9f0feea68iproto-impl: etcd_member_promote vs Cluster.MemberPromoteWrap the existing handler cluster.member_promote (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberPromote) as a Lua global etcd_member_promote callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_promote', wrap('cluster', 'member_promote')) under the appropriate service block; append 'etcd_member_promote' 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.MemberPromote 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_promote is callable from net.box:call('etcd_member_promote', {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:28ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:28ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-8t02f5cdad421dff2592e814db34d268bb5c422c47dc77c20b2e22988fec572c1a4iproto-verify: etcd_lease_keepalive vs Lease.LeaseKeepAliveAdd Lua testkit verification for etcd_lease_keepalive (mirrors gRPC Lease.LeaseKeepAlive). 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/lease. Call shape: local resp = etcd_lease_keepalive(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:00ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:00ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-8zma1dc390eef73855b175634aefef89a6b7dd681297ac7b19050c21873bd3076d4iproto-verify: etcd_role_get vs Auth.RoleGetAdd Lua testkit verification for etcd_role_get (mirrors gRPC Auth.RoleGet). 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_get(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:14ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:14ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-929a77b3b4bd7e4dc3f8e1d31816ef2336c068d67c8537564fdbbb577303e2eab52iproto-verify: etcd_maintenance_alarm vs Maintenance.AlarmAdd Lua testkit verification for etcd_maintenance_alarm (mirrors gRPC etcdserverpb.Maintenance.Alarm). 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:31ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:31ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-97v4f87a8d843ba48bb308f206711949fb0f27b6c57bf40d29c757c0f4b6fe31aediproto-verify: etcd_maintenance_hash_kv vs Maintenance.HashKVAdd Lua testkit verification for etcd_maintenance_hash_kv (mirrors gRPC etcdserverpb.Maintenance.HashKV). 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:40ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:40ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-9ar9ebaebe3d6edb221ebd924a2196864618ea9e759bacc1525a72a3ffccf586cbciproto-verify: etcd_election_proclaim vs Election.ProclaimAdd Lua testkit verification for etcd_election_proclaim (mirrors gRPC v3electionpb.Election.Proclaim). 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:46ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:46ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-9cd76af25d6915968045f137505f2614af2c364d1e305791b23a9bc113f5a28e750iproto-verify: etcd_lease_grant vs Lease.LeaseGrantAdd Lua testkit verification for etcd_lease_grant (mirrors gRPC Lease.LeaseGrant). 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/lease. Call shape: local resp = etcd_lease_grant(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:59ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:59ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-9lj5af1aed464b7f2a3ca9975c39b49b91ae39658007b617e3bee18ab295d71a074iproto-verify: etcd_user_delete vs Auth.UserDeleteAdd Lua testkit verification for etcd_user_delete (mirrors gRPC Auth.UserDelete). 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_delete(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:07ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:07ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-9z27993430a7610e43d13141d366e3b7b3f7ec6ea2063030b9d2815a2a770cf3546Phase 5f — Watch option coveragePer-option density on Watch RPCs. Big stream-shaped surface, highest remaining value but also highest effort. Run after Phase 5e. Likely tests: - TestWatchWithFilterPut / TestWatchWithFilterDelete (server-side event filtering) - TestWatchProgressNotifyExplicit (RequestProgress on demand vs the implicit 10-minute heartbeat already covered) - TestWatchWithFragment (large-response fragmentation — may surface a tarantool-side gap) - TestWatchWithPrevKV (per-watcher prev-kv flag, distinct from WithPrevKV on Put/Delete) - TestWatchFromCompactedRevision (ErrCompacted returned on the stream, not as a typed gRPC status)Each listed test ported, runs on all four cells, passes (or documented as a known gap with cross-reference).Source: docs/TODO.md "Open / Conformance matrix — Phase 5 option coverage".open2taskNULLNULL2026-05-19T13:34:06ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:06ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-a4v3156d399bad09c4b450e5716bdbf261abc162ade6d53632d4feb2288ccee49a3iproto-verify: etcd_auth_enable vs Auth.AuthEnableAdd Lua testkit verification for etcd_auth_enable (mirrors gRPC Auth.AuthEnable). 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_enable(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:03ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:03ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-acp97d1c50f3eb3e7ccc1e25dc0461f3f769efd5ef59f4e35f50d7995d0ad317a45iproto-verify: etcd_range vs KV.RangeAdd Lua testkit verification for etcd_range (mirrors gRPC KV.Range). 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/kv. Call shape: local resp = etcd_range(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:52ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:52ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ag2626fad0022546f7a8fa1aa3ad95681ae236ec2219d5303dec173c668a8c7fd31iproto-verify: etcd_user_add vs Auth.UserAddAdd Lua testkit verification for etcd_user_add (mirrors gRPC Auth.UserAdd). 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_add(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:06ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:06ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ak9a72aa034b84133ebc9e1d6502a314663ac057b4ed21dff77cd622473e65cd53fiproto-verify: etcd_auth_disable vs Auth.AuthDisableAdd Lua testkit verification for etcd_auth_disable (mirrors gRPC Auth.AuthDisable). 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_disable(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-b08e3928051dd644ec2d3c70348320e479a23d4e425c4f5776f5a2cbbfc3d571607Phase 5g — Auth/Cluster/Maintenance/Lock/Election option coveragePer-option density on the remaining v3 services. Low priority — each surface is small and the existing files already cover the canonical paths; spot-fill only what option coverage actually reveals. Run after Phase 5f.Spot-fill tests added where an unaddressed option diverges between cells; documented as a known gap otherwise.Source: docs/TODO.md "Open / Conformance matrix — Phase 5 option coverage".open3taskNULLNULL2026-05-19T13:34:10ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:10ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-bg44f65298830b799a0aa90d2dadbcb7f92f52d144db8dc119673c85221d1f7ffbaiproto-verify: etcd_role_list vs Auth.RoleListAdd Lua testkit verification for etcd_role_list (mirrors gRPC Auth.RoleList). 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_list(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:14ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:14ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-bol6e7729d0a88e476af22e1b9544083fc6358ea78739d3f4496e69e263f342d93fiproto-verify: etcd_role_add vs Auth.RoleAddAdd Lua testkit verification for etcd_role_add (mirrors gRPC Auth.RoleAdd). 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_add(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:54:12ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:12ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-bq8384f622c395002fdc1fa6c43c9005f80116e1c4c08c9aed8828a8671b4293a6biproto-verify: etcd_lease_revoke vs Lease.LeaseRevokeAdd Lua testkit verification for etcd_lease_revoke (mirrors gRPC Lease.LeaseRevoke). 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/lease. Call shape: local resp = etcd_lease_revoke(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:59ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:59ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-buq9370d11c13a9d704f0b6e3f0241d2513428257a7e3278aacfed07ddb5818c965Drop stale TODO-item-14 comment in app/etcd/json.luaapp/etcd/json.lua:621 has a stale comment: "/v3/election/observe — gated on TODO item 14". TODO item 14 closed in docs/TODO.md (the Election Observe broadcast is implemented; STREAM_HANDLERS at line 427 includes /v3/election/observe). The comment is now misleading; rewrite it to describe what the fallback branch actually catches (a streaming PATH without a handler registered) and remove the historical reference.Comment at app/etcd/json.lua:621 no longer references TODO item 14 or implies /v3/election/observe is unimplemented.Backlog. Found while auditing TODOs for the bd port on 2026-05-19.open4taskNULLNULL2026-05-19T13:34:52ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:52ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-cz54624dbf6ad6bf8e90df4dfb60839daf2c9b81d1490c3dccf619f343a0eef92fciproto-verify: etcd_maintenance_move_leader vs Maintenance.MoveLeaderAdd Lua testkit verification for etcd_maintenance_move_leader (mirrors gRPC etcdserverpb.Maintenance.MoveLeader). 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:42ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:42ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-dmtc018e2fea002b9ae10b51cd9b69a7fc6e4137e1abddda5894b9874aea50df95fiproto-verify: etcd_election_resign vs Election.ResignAdd Lua testkit verification for etcd_election_resign (mirrors gRPC v3electionpb.Election.Resign). 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:53ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:53ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-g1a94cc76ee0c10feae7cdcc327b843bb2cd907d8b2e7190c64ce7f199385cb4caaiproto-impl: etcd_member_list vs Cluster.MemberListWrap the existing handler cluster.member_list (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberList) as a Lua global etcd_member_list callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_list', wrap('cluster', 'member_list')) under the appropriate service block; append 'etcd_member_list' 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.MemberList 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_list is callable from net.box:call('etcd_member_list', {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:25ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:25ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-gz4ce1604ad8990ae56710064076900a30bc028c5a592327c484f437c820d40360ciproto-verify: etcd_put vs KV.PutAdd Lua testkit verification for etcd_put (mirrors gRPC KV.Put). 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/kv. Call shape: local resp = etcd_put(req).Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q.open3taskNULLNULL2026-05-19T14:53:53ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:53ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-h8r864b7efe5edb39f6670b5bb0ca34accb55dcf6beba77a46d7fd987280df09847iproto-verify: etcd_election_observe vs Election.ObserveAdd Lua testkit verification for etcd_election_observe (mirrors gRPC v3electionpb.Election.Observe). 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:51ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:51ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-hcoa75a35cc4e55aca16758bcde37bde3575cc73d8106697aa8e8274c5013dfdb31iproto-impl: etcd_election_observe vs Election.ObserveWrap the existing handler election.observe (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Observe) as a Lua global etcd_election_observe callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_observe', wrap('election', 'observe')) under the appropriate service block; append 'etcd_election_observe' 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.Observe 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_observe is callable from net.box:call('etcd_election_observe', {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:50ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:50ZNULLNULL0NULLNULLNULL000<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