Phoenix.Sync.Writer.Format behaviour (Phoenix.Sync v0.4.3)
View SourceDefines a behaviour that applications can implement in order to handle custom
data formats within a Phoenix.Sync.Writer
The exact format of the change messages coming from the client is
unimportant, however Phoenix.Sync.Writer
requires certain essential
information that needs to be included.
operation
- one ofinsert
,update
ordelete
relation
- the table name that the operation applies to.data
- the original data before the mutation was applied. Required forupdate
ordelete
operationschanges
- the changes to apply. Required forinsert
andupdate
operations
However you choose to encode this information on the client, you simply need
to set the format
of your write configuration using to a module that
implements this behaviour.
Implementation guide
Once you have parsed the data coming from the client, over HTTP or even raw
TCP, use Phoenix.Sync.Writer.Operation.new/4
(or
Phoenix.Sync.Writer.Transaction.operation/4
) to validate the values and
create a %Phoenix.Sync.Writer.Operation{}
struct.
Phoenix.Sync.Writer.Transaction.parse_operations/2
is a helper function for
error handling when mapping a list of encoded operation data using
Phoenix.Sync.Writer.Transaction.operation/4
.
Example:
We use Protocol buffers to encode the incoming information using :protox
and implement this module's parse_transaction/1
callback using the Protox
decode functions:
defmodule MyApp.Protocol do
use Protox,
namespace: __MODULE__,
schema: ~S[
syntax: "proto2";
message Operation {
enum Op {
INSERT = 0;
UPDATE = 1;
DELETE = 2;
}
required Op op = 1;
string table = 2;
map<string, string> original = 3;
map<string, string> modified = 4;
}
message Transaction {
repeated Operation operations = 1;
}
]
alias Phoenix.Sync.Writer
@behaviour Phoenix.Sync.Writer.Format
@impl Phoenix.Sync.Writer.Format
def parse_transaction(proto) when is_binary(proto) do
with {:ok, %{operations: ops}} <- MyApp.Protocol.Transaction.decode(proto),
{:ok, operations} <- Writer.Transaction.parse_operations(ops, &convert_operation/1) do
{:ok, %Writer.Transaction{operations: operations}
end
end
defp convert_operation(%MyApp.Protocol.Operation{} = operation) do
Writer.Transaction.operation(
operation.op,
operation.table,
operation.original,
operation.modified
)
end
end
We use our protocol module as the format
when we apply/4
our transaction
data and we can just pass our serialized protobuf message as the mutation data:
{:ok, txid, _changes} =
Phoenix.Sync.Writer.new()
|> Phoenix.Sync.Writer.apply(protobuf_data, MyApp.Repo, format: MyApp.Protocol)
Summary
Types
Raw data from a client that will be parsed to a Phoenix.Sync.Writer.Format.Transaction
by the Writer's format parser
Callbacks
Translate some data format into a Phoenix.Sync.Writer.Transaction
with a
list of operations to apply.
Types
@type parse_transaction_result() :: {:ok, Phoenix.Sync.Writer.Transaction.t()} | {:error, term()}
@type parser_fun() :: (transaction_data() -> parse_transaction_result()) | mfa()
@type t() :: module()
@type transaction_data() :: term()
Raw data from a client that will be parsed to a Phoenix.Sync.Writer.Format.Transaction
by the Writer's format parser
Callbacks
@callback parse_transaction(term()) :: parse_transaction_result()
Translate some data format into a Phoenix.Sync.Writer.Transaction
with a
list of operations to apply.