Current section

Files

Jump to
ex_esdb lib repl.ex
Raw

lib/repl.ex

defmodule ExESDB.Repl do
@moduledoc """
This module is to interact with the ExESDB.system,
running a store called "reg_gh" (Regulate Greenhouse)
"""
alias ExESDB.Repl.EventGenerator, as: ESGen
alias ExESDB.Repl.Observer, as: Observer
alias ExESDB.Repl.Producer, as: Producer
alias ExESDB.Repl.Subscriber, as: Subscriber
alias ExESDB.GatewayAPI, as: API
require Logger
@store :reg_gh
@greenhouse1 "greenhouse1"
@greenhouse2 "greenhouse2"
@greenhouse3 "greenhouse3"
@greenhouse4 "greenhouse4"
@greenhouse5 "greenhouse5"
@greenhouses [
@greenhouse1,
@greenhouse2,
@greenhouse3,
@greenhouse4,
@greenhouse5
]
def store, do: @store
def stream1, do: @greenhouse1
def stream2, do: @greenhouse2
def stream3, do: @greenhouse3
def stream4, do: @greenhouse4
def stream5, do: @greenhouse5
def get_opts, do: ExESDB.Options.app_env()
def get_streams, do: API.get_streams(@store)
def get_subscriptions, do: API.get_subscriptions(@store)
@doc """
Append events to a stream.
"""
@spec append(
stream :: atom(),
nbr_of_events :: integer()
) :: {:ok, list(), integer()} | {:error, term()}
def append(stream, nbr_of_events) do
{:ok, version} = API.get_version(@store, stream)
events = ESGen.generate_events(version, nbr_of_events)
case @store
|> API.append_events(stream, events) do
{:ok, new_version} ->
{:ok, result} =
@store
|> API.get_events(stream, 1, new_version, :forward)
{:ok, result,
result
|> Enum.count()}
{:error, reason} ->
{:error, reason}
end
end
@doc """
Starts an observer (a transient subscription) for all streams.
"""
@spec start_observer_for_all_streams() :: :ok
def start_observer_for_all_streams do
Logger.warning("Starting Observer for all streams in 5 seconds...
Switch to :observer application to see it come online.")
Process.sleep(5_000)
Observer.start(
store: @store,
type: :by_stream,
selector: "$all"
)
:ok
end
@doc """
Starts an observer (a transient subscription) for a specific stream.
## Parameters
- stream: the stream to subscribe to (default: "$greenhouse-1")
"""
@spec start_observer_for_stream(stream :: String.t()) :: :ok
def start_observer_for_stream(stream \\ "$greenhouse-1") do
Logger.warning("Starting Observer for [#{stream}] in 5 seconds...
Switch to :observer application to see it come online.")
Process.sleep(5_000)
Observer.start(
store: @store,
type: :by_stream,
selector: stream
)
:ok
end
@doc """
Starts an observer for a specific event type.
## Possible event types:
- "initialized:v1" (default)
- "temperature_measured:v1"
- "humidity_measured:v1"
- "light_measured:v1"
- "fan_activated:v1"
- "fan_deactivated:v1"
- "light_activated:v1"
- "light_deactivated:v1"
- "heater_activated:v1"
- "heater_deactivated:v1"
- "sprinkler_activated:v1"
- "sprinkler_deactivated:v1"
- "desired_temperature_set:v1"
- "desired_humidity_set:v1"
- "desired_light_set:v1"
"""
@spec start_observer_for_event_type(event_type :: String.t()) :: :ok
def start_observer_for_event_type(event_type \\ "initialized:v1") do
Logger.warning("Starting Observer for [#{event_type}] in 5 seconds...
Switch to :observer application to see it come online.")
Process.sleep(5_000)
Observer.start(
store: @store,
type: :by_event_type,
selector: event_type
)
:ok
end
@doc """
Starts an observer (a transient subscription) for a specific event payload pattern.
## Parameters
- observer_name: the name of the observer
- event_payload_pattern: the event payload pattern as a map (e.g.: %{operator: "John"})
"""
def start_observer_for_event_payload(
observer_name,
event_payload_pattern
) do
Logger.warning(
"Starting Observer for [#{observer_name}] with [#{inspect(event_payload_pattern, pretty: true)}] in 5 seconds...
Switch to :observer application to see it come online."
)
Process.sleep(5_000)
Observer.start(
store: @store,
type: :by_event_payload,
selector: event_payload_pattern,
name: observer_name
)
:ok
end
@doc """
Starts a subscriber for a specific stream.
## Parameters
- subscription_name: the name of the subscription
- stream: the stream to subscribe to (default: "$greenhouse-1")
- start_from: the version to start from (default: 0)
"""
@spec start_subscriber_for_stream(
subscription_name :: String.t(),
stream :: String.t(),
start_from :: integer()
) :: :ok
def start_subscriber_for_stream(subscription_name, stream \\ "$greenhouse-1", start_from \\ 0) do
Logger.warning(
"Starting Subscriber for [#{subscription_name}] to [#{stream}] from [#{start_from}] in 5 seconds...
Switch to :observer application to see it come online."
)
Process.sleep(5_000)
Subscriber.start(
subscription_name,
stream,
start_from
)
:ok
end
@doc """
Starts a number of producers.
Each producer will append events to a stream with stream id `greenhouse-n`.
Where n is the number of the producer.
"""
def start_producers(nbr_of_producers \\ 10) do
Logger.warning("Starting #{nbr_of_producers} Producers in 5 seconds.
Switch to :observer application to see them come online.")
Process.sleep(5_000)
1..nbr_of_producers
|> Enum.each(fn n -> Producer.start("greenhouse-#{n}") end)
:ok
end
@doc """
Stops a producer for a specific stream_id.
"""
@spec stop_producer_for_stream(stream_id :: String.t()) :: :ok
def stop_producer_for_stream(stream_id \\ "greenhouse-1") do
Producer.stop(stream_id)
end
end