Skip to content
/ clink Public

Experiment - a time tracker API built with clojure and FoundationDB

License

Notifications You must be signed in to change notification settings

bru/clink

Repository files navigation

Clink

A minimal time tracking REST API.

This project serves as a hands-on environment for exploring FoundationDB features through a realistic application written in Clojure. It aims to implement timeslip tracking (work time entries) with multi-tenant isolation, composite indexes, and query filtering.

Prerequisites

  • FoundationDB - Install the server and client libraries
  • Clojure CLI
  • Gradle - For Protocol Buffer compilation
  • Optional: Docker for containerized deployment

Quick Start

1. Compile Protocol Buffers

Before starting the service or REPL, compile the protobuf definitions:

make proto-compile

This generates Java classes from resources/proto/timeslip.proto into build/classes/java/main/.

2. Start the Service

make run
# or
clojure -M:run/service

The service starts on port 8080. Verify it's running:

curl http://localhost:8080/system-admin/status

3. Explore the API

Open the Swagger UI in your browser:

http://localhost:8080

Development

REPL Workflow

Start a REPL with development tools (Portal data inspector, Integrant REPL, hot-reload):

make repl

Once in the REPL:

;; Start the system
(start)

;; Restart (reload changed namespaces and restart)
(restart)

;; Stop the system
(stop)

;; View system configuration
(system)

Common Tasks

List all available tasks:

make

Key development commands:

make test              # Run tests with kaocha
make test-watch        # Run tests on file save
make format-check      # Check code formatting with cljstyle
make format-fix        # Fix code formatting

API Overview

Clink provides a REST API for timeslip CRUD operations and timer functionality. All endpoints require an X-Organization-ID header for multi-tenant isolation.

Main Features:

  • Create, read, update, delete timeslips
  • Start/stop timers for live time tracking
  • Query timeslips with filters (person, project, task, date range, billable status)
  • OpenAPI/Swagger documentation

Example Request:

curl -X POST http://localhost:8080/api/v1/timeslips \
  -H "Content-Type: application/json" \
  -H "X-Organization-ID: my-org" \
  -d '{
    "person-id": "person-123",
    "project-id": "project-456",
    "task-id": "task-789",
    "start-time": 1704067200000,
    "end-time": 1704070800000,
    "billable": true
  }'

For full API documentation, see the Swagger UI at http://localhost:8080.

Project Structure

├── src/bru/clink/          # Source code
│   ├── service.clj         # Entry point
│   ├── system.clj          # Integrant component lifecycle
│   ├── router.clj          # HTTP routing (Reitit)
│   ├── api/                # HTTP handlers
│   └── fdb/                # FoundationDB integration
├── resources/
│   ├── config.edn          # System configuration
│   └── proto/              # Protocol Buffer schemas
├── test/                   # Test files
└── dev/user.clj            # REPL development tools

FoundationDB Features Explored

  • Multi-tenancy: Organization-based subspace isolation
  • Record Layer: Type-safe record storage with protobuf schemas
  • Indexes: Composite indexes on (person_id, start_time) and (project_id, start_time)
  • Queries: Dynamic query builder with filtering and range scans
  • Transactions: ACID transactions with retry logic

Deployment

Build an uberjar:

make build-uberjar

Or build and run with Docker:

make docker-build

License

Copyright © 2025 Bru

Creative Commons Attribution Share-Alike 4.0 International

About

Experiment - a time tracker API built with clojure and FoundationDB

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

No packages published