Skip to content

A lightweight Java library for distributed scheduling and background work using database-backed leases.

License

Notifications You must be signed in to change notification settings

pradeesh-kumar/anthills

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

50 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🐜 Anthills

logo.png

Anthills is a lightweight distributed database-backed Job and Worker library for Java. It helps you run Scheduled Jobs and background workers safely across multiple nodes, without leader election, message queues, or extra infrastructure.

Simple Idea:

Use your database as the source of truth.

Let nodes come and go freely.


Why Anthills

Distributed coordination is hard β€” but most applications already have a database. Anthills lets you build reliable distributed systems using primitives you already trust:

  • transactions
  • timestamps
  • row-level locks

No Kafka. No ZooKeeper. No Redis locks. No leader election.

Just leases + workers.


✨ Key Features

  • βœ… Distributed-safe execution
  • πŸ” Lease-based work claiming
  • πŸ” Automatic retries with limits
  • 🧠 DB as the source of truth
  • 🚫 No duplicate execution
  • πŸͺΆ No heavyweight dependencies (no Kafka / no ORM required)

What problems does Anthills solve?

  • βœ… Run scheduled jobs on only one node
    • Even if your app runs on 10 servers.
  • βœ… Process background work across many nodes
    • With retries, backoff, and crash recovery.
  • βœ… Handle long-running tasks safely
    • Leases are automatically renewed while work runs.
  • βœ… Survive crashes and restarts
    • Expired leases allow other nodes to take over.

Core concepts

Anthills has two main primitives:

πŸ•’ LeasedScheduler

β€œRun this job periodically, but only on one node.”

Use this for:

  • cleanup jobs
  • reconciliation
  • scheduled maintenance
  • aggregation tasks
scheduler.schedule("hello-world-job", Schedule.Cron.parse("* * * * *"), () -> System.out.println("Hello world"));

Deploy this on every node β€” Anthills ensures only one executes it.


🧡 WorkRequestProcessor

β€œProcess background work across many nodes.”

Use this for:

  • email / SMS sending
  • async workflows
  • retries and compensation logic
  • event-driven processing
processor.registerHandler("notification", SendEmail.class, req -> sendEmail(req.payload()));

WorkRequest<SendEmail> request = workClient.submit(new SendEmail("hello@example.com", "Hello", "Hello from Anthills!"));

Work is:

  • persisted
  • leased
  • retried with backoff
  • safely redistributed on failure

WorkRequest

A WorkRequest represents a single unit of work stored in the database.

public record WorkRequest<T>(
  String id,
  String workType,
  T payload,
  int payloadVersion,
  String codec,
  Status status,
  int maxRetries,
  int attemptCount,
  String ownerId,
  Instant leaseUntil,
  String failureReason,
  Instant createdTs,
  Instant updatedTs,
  Instant startedTs,
  Instant completedTs
) {}

WorkRequest Status Lifecycle

New
↓
InProgress
↓
Succeeded | Failed | Cancelled

How Anthills works (high level)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Database β”‚  ← source of truth
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚
β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Leases        β”‚
β”‚ (time-bound)  β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Workers       β”‚
β”‚ (any node)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Work is claimed with a lease
  • Leases expire automatically
  • Active work renews its lease
  • Crashed nodes lose ownership
  • Other nodes recover the work

No global state. No coordination service. No single point of failure.


Project structure

anthills
β”œβ”€β”€ anthills-api       # Public interfaces & models
β”œβ”€β”€ anthills-core      # Core execution logic
β”œβ”€β”€ anthills-jdbc      # JDBC-based implementation
└── anthills-examples  # Runnable examples

Quick start

1️⃣ Add dependency

<!-- Contains API and Core implementation -->
<dependency>
  <groupId>org.anthills</groupId>
  <artifactId>anthills-core</artifactId>
  <version>${anthills.version}</version>
</dependency>

<!-- JDBC Implementation of WorkStore -->
<dependency>
  <groupId>org.anthills</groupId>
  <artifactId>anthills-jdbc</artifactId>
  <version>${anthills.version}</version>
</dependency>

2️⃣ Create a store

WorkStore store = JdbcWorkStore.create(dataSource);

3️⃣ Run a scheduled job (single-node execution)

LeasedScheduler scheduler = Schedulers.create(SchedulerConfig.defaults(), store);

scheduler.schedule("hello-world", FixedRate.every(Duration.ofSeconds(5)), () -> System.out.println("Hello from Anthills"));
scheduler.start();

Run this on multiple nodes β€” it still executes once per interval.

4️⃣ Process background work (multi-node execution)

WorkRequestProcessor processor = WorkRequestProcessors.create("notification", store, JsonPayloadCodec.defaultInstance(), ProcessorConfig.defaults());

processor.registerHandler("notification", SendEmail.class, req -> sendEmail(req.payload()));
processor.start();

Submit work from anywhere:

WorkClient workClient = WorkClients.create(workStore);
workClient.submit("notification", new SendEmail("user@example.com", "Hi", "Hello!"));

What Anthills is (and isn’t)

βœ”οΈ Anthills is

  • a distributed coordination library
  • database-backed and transaction-safe
  • simple to reason about
  • crash-resilient by design
  • framework-agnostic

❌ Anthills is not

  • a message queue
  • a stream processor
  • a workflow engine
  • a replacement for Kafka
  • a leader-election framework

Anthills is about execution guarantees, not messaging semantics.


Why database-backed leases?

Because they are:

  • already available
  • strongly consistent
  • observable
  • debuggable

You can:

  • inspect tables
  • see who owns what
  • manually intervene if needed
  • Operational transparency is a feature.

Examples

See anthills-examples for:

  • HelloWorld scheduled jobs
  • Fixed-rate vs cron scheduling
  • Distributed background workers
  • Retry and backoff behavior

Design principles

Anthills is built on a few strong principles:

  • Leases over locks
  • Failure is normal
  • Recovery over prevention
  • Simple beats clever
  • Infrastructure should be boring

Who should use Anthills?

Anthills is a great fit if you:

  • already use a relational database
  • run multiple instances of your app
  • need reliable background execution
  • want minimal infrastructure
  • value debuggability

Contributing

Contributions are welcome!

  • Areas of interest:
  • alternative persistence backends
  • metrics & observability
  • performance tuning
  • documentation & examples

Please open an issue or PR to discuss.


License

Apache License 2.0


🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜🐜

About

A lightweight Java library for distributed scheduling and background work using database-backed leases.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published