Skip to content

Commit 30cd4dd

Browse files
committed
Fixing tick logic. Instead of having the ticker genserver send tick messages to itself, have this be handled by the EventConsumer such that it starts ticking when it receives the attach event, then continuously sends tick messages to the ticker as it receives update events. This would be problematic however if there are several systems updating the same component (the ticker would get more update messages). However, it does also fix the issue of letting a system tick 'as fast as possible' in that it ensures a complete event propagation before the next tick...
1 parent b70aa23 commit 30cd4dd

3 files changed

Lines changed: 36 additions & 33 deletions

File tree

lib/ecstatic/event_consumer.ex

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,20 @@ defmodule Ecstatic.EventConsumer do
5252
w.system.process(new_entity, changes)
5353
opts when is_list(opts) ->
5454
comp = Ecstatic.Entity.find_component(new_entity, w.component)
55-
Kernel.send(ticker_pid, {:start_tick, comp.id, w.system, new_entity.id, opts})
55+
case w.component_lifecycle_hook do
56+
:updated ->
57+
case opts[:every] do
58+
:continuous -> send(state.ticker, {:tick, comp.id, new_entity.id, w.system})
59+
t when is_number(t) ->
60+
Process.send_after(
61+
state.ticker,
62+
{:tick, comp.id, new_entity.id, w.system},
63+
t
64+
)
65+
end
66+
:attached -> send(state.ticker, {:start_tick, comp.id, new_entity.id, w.system, opts})
67+
:removed -> send(state.ticker, {:stop_tick, comp.id})
68+
end
5669
end
5770
end)
5871

lib/ecstatic/ticker.ex

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
defmodule Ecstatic.Ticker do
22
defstruct [
3-
ticks: %{},
4-
entity_id: nil
3+
ticks: %{}
54
]
65
use GenServer
76

@@ -19,43 +18,29 @@ defmodule Ecstatic.Ticker do
1918
Map.put(state, :ticks, new_ticks)
2019
end
2120

22-
def handle_info({:tick, c_id, system, interval} = tick_args, state) do
21+
def handle_info({:tick, c_id, e_id, system}, state) do
2322
case Map.get(state.ticks, c_id, nil) do
2423
t_left
2524
when t_left == :infinity
2625
when (is_number(t_left) and t_left > 0) ->
2726

28-
{:ok, entity} = Ecstatic.Store.Ets.get_entity(state.entity_id)
27+
{:ok, entity} = Ecstatic.Store.Ets.get_entity(e_id)
2928
system.process(entity)
3029

31-
case interval do
32-
ms when is_number(ms) -> Process.send_after(self(), tick_args, ms)
33-
:continuous -> Kernel.send(self(), tick_args)
34-
end
35-
3630
case t_left do
3731
:infinity -> {:noreply, state}
3832
_ -> {:noreply, update_ticks(state, c_id, (t_left - 1))}
3933
end
40-
4134
0 ->
4235
{:noreply, update_ticks(state, c_id, :stopped)}
4336
:stopped ->
4437
{:noreply, state}
4538
end
4639
end
4740

48-
def handle_info({:start_tick, c_id, system, entity_id, [every: interval, for: ticks]}, state) do
49-
case Map.get(state.ticks, c_id) do
50-
^ticks -> {:noreply, state}
51-
t when t < ticks -> {:noreply, state}
52-
_ ->
53-
send(self(), {:tick, c_id, system, interval})
54-
new_state = state |>
55-
update_ticks(c_id, ticks) |>
56-
Map.put(:entity_id, entity_id)
57-
{:noreply, new_state}
58-
end
41+
def handle_info({:start_tick, c_id, e_id, system, [every: _interval, for: ticks]}, state) do
42+
send(self(), {:tick, c_id, e_id, system})
43+
{:noreply, update_ticks(state, c_id, ticks)}
5944
end
6045

6146
def handle_info({:stop_tick, c_id}, state) do

lib/ecstatic/watcher.ex

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,31 +32,36 @@ defmodule Ecstatic.Watcher do
3232

3333
defp run_ticker(system, [every: interval, for: ticks] = ticker_opts)
3434
when is_tick(ticks) and is_interval(interval) do
35-
attached =
35+
36+
base =
3637
quote location: :keep do
3738
component = Module.get_attribute(__MODULE__, :current_component)
3839
%{
3940
component: component,
40-
component_lifecycle_hook: :attached,
4141
system: unquote(system),
4242
ticker: unquote(ticker_opts)
4343
}
4444
end
4545

46+
attached =
47+
quote location: :keep do
48+
unquote(base) |> Map.put(:component_lifecycle_hook, :attached)
49+
end
50+
51+
updated =
52+
quote location: :keep do
53+
unquote(base) |> Map.put(:component_lifecycle_hook, :updated)
54+
end
55+
4656
removed =
47-
quote location: :keep do
48-
component = Module.get_attribute(__MODULE__, :current_component)
49-
%{
50-
component: component,
51-
component_lifecycle_hook: :removed,
52-
system: unquote(system),
53-
ticker: unquote(ticker_opts)
54-
}
57+
quote location: :keep do
58+
unquote(base) |> Map.put(:component_lifecycle_hook, :removed)
5559
end
5660

57-
quote location: :keep, bind_quoted: [attached: attached, removed: removed] do
61+
quote location: :keep, bind_quoted: [attached: attached, removed: removed, updated: updated] do
5862
@watchers Macro.escape(attached)
5963
@watchers Macro.escape(removed)
64+
@watchers Macro.escape(updated)
6065
end
6166
end
6267

0 commit comments

Comments
 (0)