persist document to database after 2 seconds of no updates, initialize with current state when joining genserver
This commit is contained in:
@@ -9,7 +9,7 @@ defmodule Poex.Pads.Document do
|
||||
@primary_key {:id, Ecto.UUID, autogenerate: true}
|
||||
schema "pad_documents" do
|
||||
field :title, :string
|
||||
field :state, :map, default: %{ops: []}
|
||||
field :contents, {:array, :map}, default: []
|
||||
has_many :operations, Poex.Pads.Operation
|
||||
|
||||
timestamps(type: :utc_datetime)
|
||||
@@ -18,7 +18,7 @@ defmodule Poex.Pads.Document do
|
||||
@doc false
|
||||
def changeset(document, attrs) do
|
||||
document
|
||||
|> cast(attrs, [:title, :state])
|
||||
|> cast(attrs, [:title, :contents])
|
||||
|> cast_assoc(:operations)
|
||||
end
|
||||
end
|
||||
|
@@ -1,8 +1,11 @@
|
||||
defmodule Poex.Pads.DocumentServer do
|
||||
use GenServer
|
||||
alias Poex.Pads.Document
|
||||
alias Poex.Pads
|
||||
alias Poex.Utils.DeltaUtils
|
||||
|
||||
@initial_state %{
|
||||
save_scheduled: false,
|
||||
# Number of changes made to the document so far
|
||||
version: 0,
|
||||
|
||||
@@ -36,7 +39,8 @@ defmodule Poex.Pads.DocumentServer do
|
||||
def init(args) do
|
||||
id = args.id
|
||||
Registry.register(Poex.Pads.DocumentRegistry, id, [])
|
||||
initial_state = Map.put(@initial_state, :id, id)
|
||||
%Document{contents: current_state} = Pads.get_pad_document(id)
|
||||
initial_state = Map.put(@initial_state, :id, id) |> Map.put(:contents, current_state)
|
||||
{:ok, initial_state}
|
||||
end
|
||||
|
||||
@@ -50,19 +54,28 @@ defmodule Poex.Pads.DocumentServer do
|
||||
change = DeltaUtils.convert_ops(change_map)
|
||||
inverted = Delta.invert(change, state.contents)
|
||||
|
||||
state = %{
|
||||
save_scheduled =
|
||||
if state.save_scheduled do
|
||||
true
|
||||
else
|
||||
Process.send_after(self(), :save, 2000)
|
||||
true
|
||||
end
|
||||
|
||||
new_state = %{
|
||||
id: state.id,
|
||||
save_scheduled: save_scheduled,
|
||||
version: state.version + 1,
|
||||
contents: Delta.compose(state.contents, change),
|
||||
inverted_changes: [inverted | state.inverted_changes]
|
||||
}
|
||||
|
||||
PoexWeb.Endpoint.broadcast("pad:#{state.id}", "update", %{
|
||||
PoexWeb.Endpoint.broadcast("pad:#{new_state.id}", "update", %{
|
||||
change: change,
|
||||
client_id: client_id
|
||||
})
|
||||
|
||||
{:reply, state.contents, state}
|
||||
{:reply, new_state.contents, new_state}
|
||||
end
|
||||
|
||||
# Fetch the current contents of the document
|
||||
@@ -100,6 +113,7 @@ defmodule Poex.Pads.DocumentServer do
|
||||
|
||||
state = %{
|
||||
id: state.id,
|
||||
save_scheduled: state.save_scheduled,
|
||||
version: state.version - 1,
|
||||
contents: Delta.compose(state.contents, last_change),
|
||||
inverted_changes: changes
|
||||
@@ -108,5 +122,13 @@ defmodule Poex.Pads.DocumentServer do
|
||||
{:reply, state.contents, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:save, state) do
|
||||
state = Map.put(state, :save_scheduled, false)
|
||||
Pads.update_pad_document(state.id, %{contents: state.contents})
|
||||
PoexWeb.Endpoint.broadcast("pad:#{state.id}", "saved", %{})
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
defp via_tuple(id), do: {:via, Registry, {Poex.Pads.DocumentRegistry, id}}
|
||||
end
|
||||
|
Reference in New Issue
Block a user