Setting Constant Values
The SetValue attribute sets a property to a compile-time constant whenever an event of a specified type occurs. Use it when a property should take a fixed value in response to an event — for example, setting a status flag, assigning a default category, or recording a fixed version number.
Basic Usage
Section titled “Basic Usage”using Cratis.Chronicle.Events;using Cratis.Chronicle.Keys;using Cratis.Chronicle.Projections.ModelBound;
[EventType]public record MbSetValueOrderPlaced(string CustomerName);
[EventType]public record MbSetValueOrderCanceled;
public record MbSetValueOrder( [Key] Guid Id,
[SetFrom<MbSetValueOrderPlaced>(nameof(MbSetValueOrderPlaced.CustomerName))] string CustomerName,
[SetValue<MbSetValueOrderPlaced>("active")] [SetValue<MbSetValueOrderCanceled>("canceled")] string Status);Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.SetValueOrderPlaced do use Chronicle.Events.EventType, id: "set-value-order-placed-v1"
defstruct [:customer_name]end
defmodule MyApp.Events.SetValueOrderCanceled do use Chronicle.Events.EventType, id: "set-value-order-canceled-v1"
defstruct []end
defmodule MyApp.ReadModels.SetValueOrder do use Chronicle.ReadModels.ReadModel
alias MyApp.Events.{SetValueOrderPlaced, SetValueOrderCanceled}
defstruct [:id, :customer_name, :status]
# A `$value(...)` expression sets a literal constant rather than reading a # property off the event. from SetValueOrderPlaced, set: [id: :event_source_id, customer_name: :customer_name, status: "$value(active)"]
from SetValueOrderCanceled, set: [status: "$value(canceled)"]endimport { eventType, fromEvent, Guid, readModel, setFrom, setValue } from '@cratis/chronicle';
@eventType()class MbSetValueOrderPlaced { customerName = '';}
@eventType()class MbSetValueOrderCanceled {}
@readModel()@fromEvent(MbSetValueOrderPlaced)@fromEvent(MbSetValueOrderCanceled)class MbSetValueOrder { id: Guid = Guid.empty;
@setFrom(MbSetValueOrderPlaced, 'customerName') customerName = '';
@setValue(MbSetValueOrderPlaced, 'active') @setValue(MbSetValueOrderCanceled, 'canceled') status = '';}When an OrderPlaced event occurs, Status is set to "active". When an OrderCanceled event occurs, Status is set to "canceled".
Supported Value Types
Section titled “Supported Value Types”SetValue accepts any compile-time constant: strings, integers, longs, doubles, booleans, and enum values.
[EventType]public record MbSetValueThingHappened;
public record MbSetValueThing( [Key] Guid Id,
[SetValue<MbSetValueThingHappened>("pending")] string StatusLabel,
[SetValue<MbSetValueThingHappened>(42)] int Priority,
[SetValue<MbSetValueThingHappened>(true)] bool IsActive,
[SetValue<MbSetValueThingHappened>(3.14)] double Score);Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.SetValueThingHappened do use Chronicle.Events.EventType, id: "set-value-thing-happened-v1"
defstruct []end
defmodule MyApp.ReadModels.SetValueThing do use Chronicle.ReadModels.ReadModel
alias MyApp.Events.SetValueThingHappened
defstruct [:id, status_label: "", priority: 0, is_active: false, score: 0.0]
from SetValueThingHappened, set: [ id: :event_source_id, status_label: "$value(pending)", priority: 42, is_active: true, score: "$value(3.14)" ]endimport { eventType, fromEvent, Guid, readModel, setValue } from '@cratis/chronicle';
@eventType()class MbSetValueThingHappened {}
@readModel()@fromEvent(MbSetValueThingHappened)class MbSetValueThing { id: Guid = Guid.empty;
@setValue(MbSetValueThingHappened, 'pending') statusLabel = '';
@setValue(MbSetValueThingHappened, 42) priority = 0;
@setValue(MbSetValueThingHappened, true) isActive = false;
@setValue(MbSetValueThingHappened, 3.14) score = 0;}Multiple Events
Section titled “Multiple Events”Apply the attribute more than once to respond to multiple event types:
[EventType]public record MbSetValueSubscriptionStarted;
[EventType]public record MbSetValueSubscriptionPaused;
[EventType]public record MbSetValueSubscriptionCanceled;
public record MbSetValueSubscription( [Key] Guid Id,
[SetValue<MbSetValueSubscriptionStarted>("active")] [SetValue<MbSetValueSubscriptionPaused>("paused")] [SetValue<MbSetValueSubscriptionCanceled>("canceled")] string State);Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.SetValueSubscriptionStarted do use Chronicle.Events.EventType, id: "set-value-subscription-started-v1"
defstruct []end
defmodule MyApp.Events.SetValueSubscriptionPaused do use Chronicle.Events.EventType, id: "set-value-subscription-paused-v1"
defstruct []end
defmodule MyApp.Events.SetValueSubscriptionCanceled do use Chronicle.Events.EventType, id: "set-value-subscription-canceled-v1"
defstruct []end
defmodule MyApp.ReadModels.SetValueSubscription do use Chronicle.ReadModels.ReadModel
alias MyApp.Events.{ SetValueSubscriptionStarted, SetValueSubscriptionPaused, SetValueSubscriptionCanceled }
defstruct [:id, state: ""]
from SetValueSubscriptionStarted, set: [id: :event_source_id, state: "$value(active)"]
from SetValueSubscriptionPaused, set: [state: "$value(paused)"]
from SetValueSubscriptionCanceled, set: [state: "$value(canceled)"]endimport { eventType, fromEvent, Guid, readModel, setValue } from '@cratis/chronicle';
@eventType()class MbSetValueSubscriptionStarted {}
@eventType()class MbSetValueSubscriptionPaused {}
@eventType()class MbSetValueSubscriptionCanceled {}
@readModel()@fromEvent(MbSetValueSubscriptionStarted)@fromEvent(MbSetValueSubscriptionPaused)@fromEvent(MbSetValueSubscriptionCanceled)class MbSetValueSubscription { id: Guid = Guid.empty;
@setValue(MbSetValueSubscriptionStarted, 'active') @setValue(MbSetValueSubscriptionPaused, 'paused') @setValue(MbSetValueSubscriptionCanceled, 'canceled') state = '';}SetValue vs SetFrom
Section titled “SetValue vs SetFrom”| Attribute | Source | When to use |
|---|---|---|
SetValue<TEvent>(value) | Compile-time constant | The value does not come from the event payload |
SetFrom<TEvent>(property) | Event property | The value comes from a property on the event |
Combine both on the same read model when different properties come from different sources:
[EventType]public record MbSetValueInvoiceIssued(decimal Amount);
[EventType]public record MbSetValueInvoicePaid;
public record MbSetValueInvoice( [Key] Guid Id,
[SetFrom<MbSetValueInvoiceIssued>(nameof(MbSetValueInvoiceIssued.Amount))] decimal Amount,
[SetValue<MbSetValueInvoiceIssued>("issued")] [SetValue<MbSetValueInvoicePaid>("paid")] string Status);Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.SetValueInvoiceIssued do use Chronicle.Events.EventType, id: "set-value-invoice-issued-v1"
defstruct [:amount]end
defmodule MyApp.Events.SetValueInvoicePaid do use Chronicle.Events.EventType, id: "set-value-invoice-paid-v1"
defstruct []end
defmodule MyApp.ReadModels.SetValueInvoice do use Chronicle.ReadModels.ReadModel
alias MyApp.Events.{SetValueInvoiceIssued, SetValueInvoicePaid}
defstruct [:id, amount: 0, status: ""]
from SetValueInvoiceIssued, set: [id: :event_source_id, amount: :amount, status: "$value(issued)"]
from SetValueInvoicePaid, set: [status: "$value(paid)"]endimport { eventType, fromEvent, Guid, readModel, setFrom, setValue } from '@cratis/chronicle';
@eventType()class MbSetValueInvoiceIssued { amount = 0;}
@eventType()class MbSetValueInvoicePaid {}
@readModel()@fromEvent(MbSetValueInvoiceIssued)@fromEvent(MbSetValueInvoicePaid)class MbSetValueInvoice { id: Guid = Guid.empty;
@setFrom(MbSetValueInvoiceIssued, 'amount') amount = 0;
@setValue(MbSetValueInvoiceIssued, 'issued') @setValue(MbSetValueInvoicePaid, 'paid') status = '';}