PacketFlow.DSL.Context (packetflow v0.1.0)

DSL for defining PacketFlow contexts with propagation and composition strategies

Summary

Functions

Define a context with propagation and composition strategies

Define a simple context with basic fields

Functions

defcontext(name, list)

(macro)

Define a context with propagation and composition strategies

Example

defcontext RequestContext do
  @propagation_strategy :inherit
  @composition_strategy :merge

  defstruct [:user_id, :session_id, :request_id, :capabilities, :trace]

  def new(attrs \ []) do
    struct(__MODULE__, attrs)
    |> compute_capabilities()
    |> ensure_request_id()
  end

  def propagate(context, target_module) do
    case @propagation_strategy do
      :inherit ->
        %__MODULE__{
          user_id: context.user_id,
          session_id: context.session_id,
          request_id: generate_request_id(),
          capabilities: context.capabilities,
          trace: [target_module | context.trace]
        }
      :copy ->
        %__MODULE__{
          user_id: context.user_id,
          session_id: context.session_id,
          request_id: generate_request_id(),
          capabilities: context.capabilities,
          trace: context.trace
        }
    end
  end

  def compose(context1, context2, strategy \ @composition_strategy) do
    case strategy do
      :merge ->
        %__MODULE__{
          user_id: context2.user_id,
          session_id: context2.session_id,
          request_id: generate_request_id(),
          capabilities: MapSet.union(context1.capabilities, context2.capabilities),
          trace: context1.trace ++ context2.trace
        }
      :override ->
        context2
    end
  end

  defp compute_capabilities(context) do
    capabilities = case context.user_id do
      "admin" -> MapSet.new([AdminCap.admin()])
      "user" -> MapSet.new([UserCap.basic()])
      _ -> MapSet.new([GuestCap.read()])
    end
    %{context | capabilities: capabilities}
  end

  defp generate_request_id, do: "req_311"

  defp ensure_request_id(context) do
    if context.request_id == nil do
      %{context | request_id: generate_request_id()}
    else
      context
    end
  end
end

defsimple_context(name, fields, list)

(macro)

Define a simple context with basic fields

Example

defsimple_context UserContext, [:user_id, :session_id, :capabilities] do
  @propagation_strategy :inherit
end