Skip to content

v2.0.0 — Capability tiers: universal XCapability + Instance + ReadOnly

Choose a tag to compare

@sideeffffect sideeffffect released this 12 Oct 11:53
4b354c7

Highlights

A new capability API: universal XCapability + Instance + ReadOnly tiers. This is a breaking change (#40).

  • Universal capability per building block. DaprCapability.state returns StateCapability, which reaches any store: StateCapability.save(storeName, key, value). The same holds for publish, invoke (appId per call), secrets, configuration, bindings, lock, crypto, workflow, actor, and, on the JVM, jobs and conversation.
  • Narrow by name with instance(name). It returns XCapability.Instance, bound to one resource: dapr.state.instance(store).get[T](key).
  • Narrow by authority with ReadOnly. State, Secrets, Configuration, Jobs and Workflow have X.ReadOnly and X.Instance.ReadOnly. Narrowing a read-only capability by name stays read-only, which the compiler checks.
  • Actor has two levels: ActorCapability.forType(actorType).instance(actorId).
  • Companion forwarders and accessors on every interface. For example, StateCapability.Instance.save(key, v) uses the capability in using scope, and StateCapability.ReadOnly.instance(store) returns the narrowed capability.
  • Handle-style sugar that respects the tiers:
    • WorkflowInstanceId: id.waitForCompletion(timeout) and id.getStatus need only WorkflowCapability.ReadOnly; id.suspend(), id.terminate() and the other mutations need WorkflowCapability.
    • JobName (JVM): name.get, name.scheduleOnce(...) and name.delete().
  • One package per family: dapr4s.state, dapr4s.invoke, dapr4s.workflow and so on. Cross-cutting types stay in dapr4s.

Migrating from 1.x

  • Add family imports, e.g. import dapr4s.state.*, dapr4s.workflow.*.
  • Code that is bound to one store, inside a DaprCapability.state(name) { ... } block, now uses StateCapability.Instance. For example, (using StateCapability) becomes (using StateCapability.Instance), and StateCapability.get(key) becomes StateCapability.Instance.get(key).
  • dapr.state(name) becomes dapr.state.instance(name). dapr.actor(t)(id) becomes dapr.actor.forType(t).instance(id).
  • These types were removed: Access*Capability, WorkflowInstanceCapability, ActorTypeCapability and JobCapability.
  • dapr4s-examples shows the full migration.

Features

  • Universal / Instance / ReadOnly capability tiers for all building blocks; derivation macros require the narrowest tier (#40).
  • Tier-aware handle sugar on WorkflowInstanceId and JobName (#40).
  • One package per capability family (#40).

Fixes

  • Scaladoc: 94 unresolved links fixed. JVM and Scala.js scaladoc now report 0 warnings.

Build / CI

  • Fixed a silent hang in the Scala.js integration tests. scala-cli chose __loader.js instead of main.js as the Wasm test entry when its temp dir was on ext4. The test harness now runs scala-cli with its temp dir on tmpfs. Upstream fix: VirtusLab/scala-cli#4548.
  • scala-cli is pinned to 1.14.0, because newer versions with the Scala.js 1.22 linker cannot link js.async on Wasm without a JSPI switch. The integration step now has a 20-minute timeout.
  • Publishes of the same version are serialized with a concurrency group.

Docs

  • New docs/CAPABILITY-HIERARCHY.md: one Mermaid class diagram per capability family.
  • docs/CAPABILITY-SPLITS.md §11 describes the implemented design. DESIGN.md, README and SPEC.allium are updated, and allium check reports 0 errors.