//// Data integration patterns for ecosystem compatibility (M26).
import gleam/int
import lightspeed/data/repository
/// Migration-track strategy for integrating data boundaries.
pub type MigrationTrack {
DualWriteFirst
ReadReplicaFirst
BigBangCutover
}
/// One data integration pattern.
pub type Pattern {
Pattern(
name: String,
adapter: repository.Adapter,
migration_track: MigrationTrack,
scope_enforced: Bool,
retry_budget: Int,
read_after_write_check: Bool,
)
}
/// CRUD-oriented mixed-runtime data pattern.
pub fn crud_pattern() -> Pattern {
Pattern(
name: "crud_mixed_runtime",
adapter: repository.MixedBridge(
read_module: "MyApp.RepoRead",
write_module: "MyApp.RepoWrite",
),
migration_track: DualWriteFirst,
scope_enforced: True,
retry_budget: 3,
read_after_write_check: True,
)
}
/// Event-stream oriented data pattern.
pub fn event_stream_pattern() -> Pattern {
Pattern(
name: "event_stream_bridge",
adapter: repository.ElixirBridge(module: "MyApp.EventStore"),
migration_track: ReadReplicaFirst,
scope_enforced: True,
retry_budget: 5,
read_after_write_check: True,
)
}
/// In-memory local development fallback pattern.
pub fn local_dev_pattern() -> Pattern {
Pattern(
name: "local_dev_in_memory",
adapter: repository.GleamInMemory,
migration_track: BigBangCutover,
scope_enforced: True,
retry_budget: 1,
read_after_write_check: True,
)
}
/// Validate data integration constraints.
pub fn valid(pattern: Pattern) -> Bool {
pattern.scope_enforced
&& pattern.retry_budget > 0
&& pattern.read_after_write_check
&& adapter_track_compatible(pattern.adapter, pattern.migration_track)
}
/// Stable migration-track label.
pub fn migration_track_label(track: MigrationTrack) -> String {
case track {
DualWriteFirst -> "dual_write_first"
ReadReplicaFirst -> "read_replica_first"
BigBangCutover -> "big_bang_cutover"
}
}
/// Stable pattern signature.
pub fn signature(pattern: Pattern) -> String {
"data:"
<> pattern.name
<> "|adapter="
<> repository.adapter_label(pattern.adapter)
<> "|track="
<> migration_track_label(pattern.migration_track)
<> "|scope_enforced="
<> bool_label(pattern.scope_enforced)
<> "|retry_budget="
<> int.to_string(pattern.retry_budget)
<> "|read_after_write_check="
<> bool_label(pattern.read_after_write_check)
}
/// Pattern adapter.
pub fn adapter(pattern: Pattern) -> repository.Adapter {
pattern.adapter
}
/// Pattern name.
pub fn name(pattern: Pattern) -> String {
pattern.name
}
fn adapter_track_compatible(
adapter: repository.Adapter,
track: MigrationTrack,
) -> Bool {
case adapter, track {
repository.GleamInMemory, BigBangCutover -> True
repository.GleamInMemory, _ -> False
_, _ -> True
}
}
fn bool_label(value: Bool) -> String {
case value {
True -> "true"
False -> "false"
}
}