zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

pipeline_serializer.ex (1880B)


      1 defmodule Absinthe.Subscription.PipelineSerializer do
      2   @moduledoc """
      3   Serializer responsible for packing and unpacking pipeline stored in the Elixir registry.
      4 
      5   The purpose of this logic is saving memory by deduplicating repeating options - (ETS
      6   backed registry stores them flat in the memory).
      7   """
      8 
      9   alias Absinthe.{Phase, Pipeline}
     10 
     11   @type options_label :: {:options, non_neg_integer()}
     12 
     13   @type packed_phase_config :: Phase.t() | {Phase.t(), options_label()}
     14 
     15   @type options_map :: %{options_label() => Keyword.t()}
     16 
     17   @type packed_pipeline :: {:packed, [packed_phase_config()], options_map()}
     18 
     19   @spec pack(Pipeline.t()) :: packed_pipeline()
     20   def pack(pipeline) do
     21     {packed_pipeline, options_reverse_map} =
     22       pipeline
     23       |> List.flatten()
     24       |> Enum.map_reduce(%{}, &maybe_pack_phase/2)
     25 
     26     options_map = Map.new(options_reverse_map, fn {options, label} -> {label, options} end)
     27 
     28     {:packed, packed_pipeline, options_map}
     29   end
     30 
     31   @spec unpack(Pipeline.t() | packed_pipeline()) :: Pipeline.t()
     32   def unpack({:packed, pipeline, options_map}) do
     33     Enum.map(pipeline, fn
     34       {phase, {:options, _n} = options_label} ->
     35         {phase, Map.fetch!(options_map, options_label)}
     36 
     37       phase ->
     38         phase
     39     end)
     40   end
     41 
     42   def unpack([_ | _] = pipeline) do
     43     pipeline
     44   end
     45 
     46   defp maybe_pack_phase({phase, options}, options_reverse_map) do
     47     if Map.has_key?(options_reverse_map, options) do
     48       options_label = options_reverse_map[options]
     49 
     50       {{phase, options_label}, options_reverse_map}
     51     else
     52       new_index = map_size(options_reverse_map)
     53       options_label = {:options, new_index}
     54       options_reverse_map = Map.put(options_reverse_map, options, options_label)
     55 
     56       {{phase, options_label}, options_reverse_map}
     57     end
     58   end
     59 
     60   defp maybe_pack_phase(phase, options_reverse_map) do
     61     {phase, options_reverse_map}
     62   end
     63 end