Liking cljdoc? Tell your friends :D

version-vector

⚠️ Project Renamed: This project was previously net.clojars.bru/vector-clock. That artifact is deprecated. Please migrate to net.clojars.bru/version-vector.

Version vector implementation for Clojure and ClojureScript.

Overview

This library provides version vectors for building distributed systems in both Clojure (JVM) and ClojureScript.

Version Vectors - A mechanism for determining causality and detecting conflicts in distributed systems.

This implementation uses a map where keys represent devices in a distributed db, and values represent the version last contributed by that device.

Features

  • CRDT Operations: tick, check, merge operations for version vectors
  • Causality Detection: Determine if events are concurrent, causally related, or identical
  • Well-Tested: Comprehensive test suite including property-based tests

Installation

Add to your deps.edn:

{:deps {net.clojars.bru/version-vector {:mvn/version "0.2.0"}}}

Platform Support

This library is written in .cljc (cross-platform Clojure) and works in both:

  • Clojure (JVM): Server-side applications, backend services
  • ClojureScript: Browser applications, Node.js, React Native

The core algorithm uses only platform-agnostic Clojure functions with no dependencies.

Testing: Tests run on Clojure only. Since the implementation is 100% platform-agnostic with no JavaScript interop or ClojureScript-specific features, Clojure testing should provide sufficient coverage.

Quick Start

(ns my-app.sync
  (:require [version-vector.core :as vv]))

;; Create a clock for this device
(def my-clock (vv/make-clock "device-1"))

;; Increment the clock when making changes
(def updated-clock (vv/tick my-clock "device-1"))
; => {"device-1" 1}

;; Compare with another device's clock
(def other-clock {"device-2" 1})
(vv/check updated-clock other-clock)
; => :concurrent (both devices made independent changes)

;; Merge clocks when syncing
(def merged (vv/merge-clocks updated-clock other-clock))
; => {"device-1" 1 "device-2" 1}

Version Vector API

Core Operations

make-clock

(make-clock device-id)

Create a new vector clock for the given device ID.

tick

(tick clock device-id)

Increment the counter for the specified device. Returns a new clock.

check

(check this-clock other-clock)

Compare two clocks and return their causal relationship:

  • :same - Clocks are identical
  • :ancestor - this-clock causally precedes other-clock
  • :descendant - this-clock causally follows other-clock
  • :concurrent - Neither causally precedes the other (conflict!)

merge-clocks

(merge-clocks clock1 clock2)

Merge two clocks by taking the maximum value for each device. Used when synchronizing state across devices.

Usage Examples

Detecting Conflicts

(require '[version-vector.core :as vv])

;; Device 1 makes a change
(def device1-clock (vv/tick (vv/make-clock "d1") "d1"))
; => {"d1" 1}

;; Device 2 makes an independent change
(def device2-clock (vv/tick (vv/make-clock "d2") "d2"))
; => {"d2" 1}

;; Check for conflicts
(vv/check device1-clock device2-clock)
; => :concurrent (conflict detected!)

Synchronization Workflow

Example: distributed note taking app

(defrecord Note [id content clock])

(defn update-note [note new-content device-id]
  (->Note (:id note)
          new-content
          (vv/tick (:clock note) device-id)))

(defn merge-notes [note1 note2]
  (case (vv/check (:clock note1) (:clock note2))
    (:same :ancestor) note2  ; Keep newer version
    :descendant note1        ; Keep newer version
    :concurrent              ; Conflict - needs resolution strategy
    (->Note (:id note1)
            (str (:content note1) "\n---CONFLICT---\n" (:content note2))
            (vv/merge-clocks (:clock note1) (:clock note2)))))

Testing

Run tests on Clojure:

clojure -X:test

All tests run on the JVM. The library works in ClojureScript projects but is only tested on Clojure since the implementation is platform-agnostic.

License

Copyright © 2025

Distributed under the Eclipse Public License version 1.0.

References

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close