Skip to content

feat(plugin-memcached): add a Memcached driver over the text protocol - #3980

Merged
datlechin merged 8 commits into
TableProApp:mainfrom
J2TeamNNL:feat/plugin-memcached
Nov 1, 2026
Merged

datlechin merged 8 commits into
TableProApp:mainfrom
J2TeamNNL:feat/plugin-memcached

Conversation

@J2TeamNNL

@J2TeamNNL J2TeamNNL commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • New registry plugin MemcachedDriverPlugin over the text protocol, on SwiftNIO the way the Kafka plugin is. Parsing lives in a new PluginKit-free product, TableProMemcachedCore: the console parser, an incremental reply reader, the key listing parsers and the grid's browse spec.
  • Connection form: host, port 11211, username and password, SSL through NIOSSL, SSH tunnel and the other port forwards.
  • How keys are found: the text protocol has no key listing, so the driver reads stats settings at connect. With lru_crawler yes (1.4.31 and later, the default) it lists keys with lru_crawler metadump all on a short-lived second connection, because a metadump cannot share a connection with other commands. Otherwise, or when the server refuses the metadump, it falls back to stats items plus stats cachedump <slab> 0 per slab class. That list is a capped sample, and the table's comment says so. A listing stops at 1,000,000 keys and the extra connection is closed.
  • One keys table with the item count from stats. Grid columns Key, Value, TTL and Flags. Values come from one multi-key get per 100 rows of the current page. TTL is the metadump or cachedump expiry minus the server's own time, empty for no expiry.
  • Sorting is by key. Filters apply to Key only (=, !=, contains, starts with, ends with, IN, NOT IN, regex). A filter on another column is refused with a message, because filtering on Value would read every value.
  • Edits: a changed Value or Flags runs set with the absolute time the item already expires at, so the save neither extends nor revives it; a TTL alone runs touch; a new row runs set; a deleted row runs delete. Key is immutable, and a key holding a quote is quoted in the statement. A TTL over 30 days is sent as the time it ends, since memcached reads a larger exptime as a Unix time. Truncate runs flush_all.
  • The editor runs get, gets, gat, gats, set, add, replace, append, prepend, cas, touch, delete, incr, decr, flush_all, stats, version and lru_crawler metadump. Arguments follow the protocol, with the value as the last argument instead of a data block, quoted with \n, \xHH and similar escapes. Anything else is refused before it reaches the server.
  • Query classifier: reads and the reading stats forms are safe, stores and stats reset, stats detail on or stats sizes_enable write, delete and flush_all are destructive.
  • Server Dashboard: used memory, items, hit ratio, evictions, connections and uptime from stats.
  • Registry entry, curated metadata, DatabaseType.memcached and the SF Symbol memorychip as icon (no brand mark in Simple Icons).

Defaults I picked, open to change:

  • Auth uses the text protocol login of a server started with -Y <auth file> (1.5.15 and later). The driver sends the credentials only after the server refuses version with CLIENT_ERROR unauthenticated, so an open server never stores them as an item. SASL is left out: it needs the binary protocol, which memcached marks deprecated, and a SASL server refuses the text commands the key listing needs.
  • One table for the whole server, since memcached has no namespaces.
  • The listing cap is 1,000,000 keys.

Docs: TableProApp/docs#156

Test plan

  • swift test --filter TableProMemcachedCoreTests: the console parser and its quoting round trip (UTF-8 and raw bytes), the reply reader fed in pieces (a CRLF inside a value, the line limit, every error line), metadump and cachedump lines, slab classes, the browse spec's paging, sorting and every key comparison, and the write statements.
  • Hosted: QueryClassifierHardeningTests (Memcached tiers), MemcachedDashboardProviderTests, and Memcached added to the factory, gate, listing, base query, parameter detection and type count suites. DatabaseTypeTests counts the new type.
  • Live: apple/scripts/probes/check-memcached.sh runs the plugin's own sources against memcached 1.6.45 and 1.4.39 in Docker through an SSH tunnel. Every check passes on 1.6.45 (metadump), 1.4.39 (crawler off, cachedump fallback) and 1.6.45 with an auth file (no credentials and a wrong password fail with their own messages): paging with offsets, sort, every filter, TTLs, flags, escaped and quoted keys and values, set, touch, delete, insert, a value edit that keeps the expiry, incr, add on an existing key, stats, stats reset, stats cachedump and lru_crawler metadump. A silent endpoint fails with a timeout. A key touched just before a metadump is sometimes missing from that one walk; the server moves items between LRU segments during the crawl, so the docs say a listing is not a snapshot.
  • xcodebuild -scheme MemcachedDriverPlugin build succeeds. The app target compiles; the hosted test bundle did not finish locally because the disk filled, so CI runs those suites.

Fixes #2483

# Conflicts:
#	apple/TablePro/Core/Plugins/PluginMetadataRegistry+RegistryDefaults.swift
#	apple/TablePro/Resources/Localizable.xcstrings
#	apple/TableProTests/Core/Plugins/PluginMetadataRegistryTypeCountTests.swift
@J2TeamNNL

Copy link
Copy Markdown
Contributor Author

macOS Tests fails in "Build for testing" with value of type 'MenuValidationContext' has no member 'isCurrentTabEditable'. That comes from main, not this PR: since 4e36b34 (#3961) TableProTests/Core/Menu/MainMenuBuilderTests.swift:789 sets a member MenuValidationContext does not have. This PR touches neither file. SwiftLint, Repo Hygiene and iOS and Package Tests pass. I will merge main again once it is fixed.

@datlechin
datlechin enabled auto-merge (squash) November 1, 2026 09:09
@datlechin
datlechin merged commit be149c8 into TableProApp:main Nov 1, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memcached support

2 participants