Skip to content

Latest commit

 

History

History
122 lines (94 loc) · 3.99 KB

README.md

File metadata and controls

122 lines (94 loc) · 3.99 KB

jsr

Actors

High-scale interactive services often demand a combination of high throughput, low latency, and high availability. These are challenging goals to meet with traditional stateless architectures. Inspired by the Orleans virtual-actor pattern, the Actors library offers a stateful solution, enabling developers to manage distributed state in a seamless and scalable way.

The Actors model simplifies the development of stateful applications by abstracting away the complexity of distributed system concerns, such as reliability and resource management. This allows developers to focus on building logic while the framework handles the intricacies of state distribution and fault tolerance.

With Actors, developers create "actors" – isolated, stateful objects that can be invoked directly. Each actor is uniquely addressable, enabling efficient and straightforward interaction across distributed environments.

Key Features

  • Simplified State Management: Build stateful services using a straightforward programming model, without worrying about distributed systems complexities like locks or consistency.
  • No Distributed Locks: Actors handle state independently, eliminating the need for distributed locks. Each actor is responsible for its own state, making it simple to work with highly concurrent scenarios without race conditions.
  • Virtual Actors: Actors are automatically instantiated, managed, and scaled by the framework, freeing you from managing lifecycles manually.
  • Powered by Deno Cluster Isolates: Achieve high-performance applications that scale effortlessly by leveraging Deno cluster's unique isolate addressing.

Example: Simple Atomic Counter without Distributed Locks

import { actors, ActorState } from "@deco/actors";

class Counter {
  private count: number;

  constructor(protected state: ActorState) {
    this.count = 0;
    state.blockConcurrencyWhile(async () => {
      this.count = await this.state.storage.get<number>("counter") ?? 0;
    });
  }

  async increment(): Promise<number> {
    await this.state.storage.put("counter", ++this.count);
    return this.count;
  }

  getCount(): number {
    return this.count;
  }
}

// Invoking the counter actor
const counter = actors.stub(Counter).id("counter-id");
// Increment counter
await counter.increment();
// Get current count
const currentCount = await counter.getCount();
console.log(`Current count: ${currentCount}`);

Cloudflare Workers

The framework now supports Cloudflare Workers through Durable Objects, providing the same actor model with CF's global distribution and reliability.

To deploy your actors on Cloudflare Workers:

  1. Create your worker script (using Hono):
import { ActorCfRuntime, Env } from "@deco/actors/cf";
import { withActors } from "@deco/actors/hono";
import { Hono } from "hono";
import { Counter } from "./counter.ts";
export { ActorDurableObject } from "@deco/actors/cf";

const app = new Hono<{ Bindings: Env }>();

const runtime = new ActorCfRuntime([Counter]);
app.use(withActors(runtime));

app.get("/", (c) => c.text("Hello Cloudflare Workers!"));

export default app;
  1. Configure your wrangler.toml
#:schema node_modules/wrangler/config-schema.json
compatibility_flags = ["nodejs_compat"]
name = "counter-actor"
main = "src/index.ts"
compatibility_date = "2024-11-27"

# Workers Logs
# Docs: https://developers.cloudflare.com/workers/observability/logs/workers-logs/
# Configuration: https://developers.cloudflare.com/workers/observability/logs/workers-logs/#enable-workers-logs
[observability]
enabled = true

[[durable_objects.bindings]]
name = "ACTOR_DO"
class_name = "ActorDurableObject"

# Durable Object migrations.
# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
[[migrations]]
tag = "v1"
new_classes = ["ActorDurableObject"]

You check the full example here