memcached

Memcached client for Kit using vendored mcmc C bindings

Files

FileDescription
.editorconfigEditor formatting configuration
.gitignoreGit ignore rules for build artifacts and caches
.tool-versionsasdf tool versions (Zig, Kit)
LICENSEMIT license file
README.mdThis file
c/kit_memcached.cC FFI wrapper over the vendored memcached client
c/kit_memcached.hC header for the FFI wrapper
c/vendor/mcmc/Vendored upstream mcmc C client
examples/basic.kitBasic connection, version, set, get, and delete example
examples/cas.kitExample: gets plus cas flow
examples/live-smoke.kitBroader live smoke example covering the client surface
examples/memcached.kitCanonical example with multi-key reads and stats
kit.tomlPackage manifest with metadata and native build config
src/memcached.kitkit-memcached client API for Kit
tests/memcached.test.kitLive tests for the memcached client

Dependencies

No Kit package dependencies.

This package vendors the upstream mcmc C client in c/vendor/mcmc/, so no external memcached client library is required at build time.

Runtime examples and tests need a reachable memcached server. The package requires the ffi and tcp capabilities.

Installation

kit add gitlab.com/kit-lang/packages/kit-memcached.git

Usage

import Kit.Memcached as Memcached

main = fn =>
  # Open a TCP connection to memcached.
  match Memcached.connect "127.0.0.1" 11211
    | Err err ->
      println "Failed to connect: ${show err}"
    | Ok client ->
      # Ensure the client handle is closed when we exit this scope.
      defer Memcached.close client

      key-a = "greeting"
      key-b = "subject"
      missing-key = "missing"

      # Store and fetch values.
      Memcached.delete client key-a |> Result.unwrap
      Memcached.delete client key-b |> Result.unwrap
      Memcached.set client key-a "hello" |> Result.unwrap
      Memcached.set client key-b "memcached" |> Result.unwrap

      greeting = Memcached.get client key-a |> Result.unwrap
      println "greeting=${show greeting}"

      # Fetch multiple keys. Missing keys are omitted from the map.
      values = Memcached.get-many client [key-a, key-b, missing-key] |> Result.unwrap
      println "a=${show (Map.get key-a values)}"
      println "b=${show (Map.get key-b values)}"
      println "missing=${show (Map.get missing-key values)}"

      # Use gets/cas when writes need compare-and-swap protection.
      fetched = Memcached.gets client key-a |> Result.unwrap
      match fetched
        | Some (MemcachedCasValue {token, ..}) ->
          result = Memcached.cas client key-a token "hello again" |> Result.unwrap
          println "cas=${show result}"
        | None ->
          println "unexpected missing value"

      # Read server metadata.
      version = Memcached.version client |> Result.unwrap
      stats = Memcached.stats client |> Result.unwrap
      println "version=${version}"
      println "pid=${show (Map.get "pid" stats)}"

main

Supported API areas:

  • TCP connection management with connect, close, is-connected?
  • Storage commands: set, set-ex, add, add-ex, replace, replace-ex, append, prepend
  • Retrieval commands: get, get-many, gets, gets-many
  • CAS commands: cas, cas-ex
  • Mutation and admin commands: delete, touch, flush-all, incr, decr
  • Server metadata: version, stats-text, stats, stats-settings-text, stats-settings, stats-slabs-text, stats-slabs, stats-items-text, stats-items

Development

Local memcached daemon

Live examples and tests expect a memcached daemon to be available. The test suite uses port 11222:

memcached -p 11222 -U 0 -l 127.0.0.1

Examples default to 127.0.0.1:11211, but can be pointed at the same test daemon:

KIT_MEMCACHED_HOST=127.0.0.1 KIT_MEMCACHED_PORT=11222 kit run --allow=ffi,tcp examples/memcached.kit

Running Examples

Run the basic example with the interpreter:

KIT_MEMCACHED_HOST=127.0.0.1 KIT_MEMCACHED_PORT=11222 kit run --allow=ffi,tcp examples/basic.kit

Run the CAS example:

KIT_MEMCACHED_HOST=127.0.0.1 KIT_MEMCACHED_PORT=11222 kit run --allow=ffi,tcp examples/cas.kit

Compile the live smoke example to a native binary:

kit build --allow=ffi,tcp examples/live-smoke.kit --no-spinner -o /tmp/kit_memcached_live_smoke
/tmp/kit_memcached_live_smoke

The examples use defer Memcached.close client after a successful connect, which is the intended cleanup pattern for the client handle returned by this package.

Running Tests

Run the live test suite:

kit test tests/memcached.test.kit

Run the test suite with coverage:

kit test tests/memcached.test.kit --coverage

Running kit dev

Run the standard development workflow (format, check, examples, test):

kit dev

This will:

  1. Rebuild the native library when needed
  2. Format and check source files in src/
  3. Type check examples in examples/
  4. Run tests in tests/ with coverage

Running Parity

Compare interpreter output with compiled binary output for examples:

kit parity --no-spinner --failures-only

Parity results are written to timestamped *-results.txt files.

Generating Documentation

Generate API documentation from doc comments:

kit doc

Note: Kit sources with doc comments (##) will generate HTML documents in docs/*.html.

Cleaning Build Artifacts

Remove generated files, caches, parity results, and build artifacts:

kit task clean

Note: Defined in kit.toml.

Local Installation

To install this package locally for development:

kit install

This installs the package to ~/.kit/packages/@kit/memcached/, making it available for import as Kit.Memcached in other projects.

License

This package is released under the MIT License - see LICENSE for details.

The vendored upstream mcmc client in c/vendor/mcmc/ is also released under the MIT License.

Exported Functions & Types

MemcachedError

Memcached client error type. Connection errors report failed socket setup, while command errors report failures from commands issued on an existing connection.

Variants

MemcachedConnectionError {message}
MemcachedCommandError {message}

MemcachedCasValue

Value returned by gets and gets-many, including the CAS token.

Variants

MemcachedCasValue {value, token}

MemcachedCasResult

Result of a CAS write.

Variants

MemcachedCasStored
MemcachedCasExists
MemcachedCasNotFound

connect

Open a TCP connection to a memcached server.

NonEmptyString -> PositiveInt -> Result Ptr MemcachedError

close

Close a memcached client handle.

Ptr -> Unit

is-connected?

Check whether the client handle is still connected.

Ptr -> Bool

set

Store a value without expiration.

Ptr -> String -> String -> Result Unit MemcachedError

set-ex

Store a value with an expiration time in seconds.

Ptr -> String -> PositiveInt -> String -> Result Unit MemcachedError

add

Store a value only when the key is missing. Returns true when the key was created and false when it already existed.

Ptr -> String -> String -> Result Bool MemcachedError

add-ex

Store a value with expiration only when the key is missing. Returns true when the key was created and false when it already existed.

Ptr -> String -> PositiveInt -> String -> Result Bool MemcachedError

replace

Replace an existing value without expiration. Returns true when the key existed and was replaced.

Ptr -> String -> String -> Result Bool MemcachedError

replace-ex

Replace an existing value with an expiration time in seconds. Returns true when the key existed and was replaced.

Ptr -> String -> PositiveInt -> String -> Result Bool MemcachedError

append

Append text to an existing value. Returns true when the key existed and was updated.

Ptr -> String -> String -> Result Bool MemcachedError

prepend

Prepend text to an existing value. Returns true when the key existed and was updated.

Ptr -> String -> String -> Result Bool MemcachedError

get

Get one value by key. Returns None when the key is missing.

Ptr -> String -> Result (Option String) MemcachedError

gets

Get one value and its CAS token by key. Returns None when the key is missing.

Ptr -> String -> Result (Option MemcachedCasValue) MemcachedError

get-many

Get multiple values by key. Missing keys are omitted from the returned map.

Ptr -> List String -> Result (Map String String) MemcachedError

gets-many

Get multiple values and CAS tokens by key. Missing keys are omitted from the returned map.

Ptr -> List String -> Result (Map String MemcachedCasValue) MemcachedError

cas

Compare-and-swap a value without expiration using a CAS token from gets.

Ptr -> String -> String -> String -> Result MemcachedCasResult MemcachedError

cas-ex

Compare-and-swap a value with an expiration time in seconds.

Ptr -> String -> PositiveInt -> String -> String -> Result MemcachedCasResult MemcachedError

delete

Delete a key. Returns true when the key existed and was deleted.

Ptr -> String -> Result Bool MemcachedError

touch

Update a key's expiration time in seconds. Returns true when the key existed and was touched.

Ptr -> String -> PositiveInt -> Result Bool MemcachedError

flush-all

Flush all keys from the connected memcached server.

Ptr -> Result Unit MemcachedError

incr

Increment a numeric value by the provided amount. Returns None when the key is missing.

Ptr -> String -> PositiveInt -> Result (Option Int) MemcachedError

decr

Decrement a numeric value by the provided amount. Returns None when the key is missing.

Ptr -> String -> PositiveInt -> Result (Option Int) MemcachedError

version

Get the memcached server version string.

Ptr -> Result String MemcachedError

stats-text

Get raw stats output as newline-separated key=value text.

Ptr -> Result String MemcachedError

stats-settings-text

Get raw stats settings output as newline-separated key=value text.

Ptr -> Result String MemcachedError

stats-slabs-text

Get raw stats slabs output as newline-separated key=value text.

Ptr -> Result String MemcachedError

stats-items-text

Get raw stats items output as newline-separated key=value text.

Ptr -> Result String MemcachedError

stats

Get parsed stats output as a map.

Ptr -> Result (Map String String) MemcachedError

stats-settings

Get parsed stats settings output as a map.

Ptr -> Result (Map String String) MemcachedError

stats-slabs

Get parsed stats slabs output as a map.

Ptr -> Result (Map String String) MemcachedError

stats-items

Get parsed stats items output as a map.

Ptr -> Result (Map String String) MemcachedError