Phoenix.Sync.Writer.Format behaviour (Phoenix.Sync v0.6.1)
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 of- insert,- updateor- delete
- relation- the table name that the operation applies to.
- data- the original data before the mutation was applied. Required for- updateor- deleteoperations
- changes- the changes to apply. Required for- insertand- updateoperations
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
endWe 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.