Proca.Server.Processing (proca v3.3.1)

For these cases:

  1. We receive Actions with Supporter or with unbound ref.
  2. Action with supporter may have new or resolved supporter (by ref).
  3. Action with unbound ref will be bound later.

Processing works in following way:

  1. Process supporter, then action.
  2. Process supporter.
  3. ignore. This is a case where we store action for counts (share, tweet without any contact, and it might never arrive). On the other hand, it would be nice to have this later in CRM right?

State diagram below shows transitions while processing. A stands for Action, S for supporter. States are enumerated in ProcessingStatus, and supporter and action track its status separately.

    [ A(NEW) / nil ]
        | linking
        v
    [ A(NEW) / S(NEW) ]            <-----.  linking new action to rejected supporter
        | emit to supporter confirm      | 
        v                                |  
    [ A(NEW) / S(CONFIRMING)] -> [ A(REJECTED) / S(REJECTED) ] --> stop (and remove the cookie?!)
        | confirm 
        v
  ,->[ A(NEW) / S(ACCEPTED)]
  |     | emit to action confirm
n |     v
e |  [ A(CONFIRMING) / S(ACCEPTED)] -> [ A(REJECTED) / S(ACCEPTED)] --> stop
w |     | confirm
  |     v
  '--[ A(ACCEPTED) / S(ACCEPTED)] -> [ A(DELIVERED) / S(ACCEPTED)] --> stop
                                 emit

This mechanism is supposed to be able to run many times with same result if action and supporter bits do not change.

At the moment we do not support custom action confirmation - fully - we do not send actions to this queue and there is not routes in API to confirm or reject an action. This is a missing piece albeit for now did not proove necessary.

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

This method emits an effect on transition.

Rank supporter when entering

A noop sync method that lets you make sure all previous async messages were processed (used in testing)

This function implements the state machine for Action. It returns a changeset to update action/supporter (state) and atoms telling where to route action.

Link to this section Functions

Link to this function

change_status(action, action_status, supporter_status)

Link to this function

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

clear_transient(action)

Link to this function

emit(action, entity, arg3)

Specs

emit(
  action :: %Proca.Action{
    __meta__: term(),
    action_page: term(),
    action_page_id: term(),
    action_type: term(),
    campaign: term(),
    campaign_id: term(),
    donation: term(),
    fields: term(),
    id: term(),
    inserted_at: term(),
    messages: term(),
    processing_status: term(),
    ref: term(),
    source: term(),
    source_id: term(),
    supporter: term(),
    supporter_id: term(),
    testing: term(),
    updated_at: term(),
    with_consent: term()
  },
  :action | :supporter,
  :confirm | :deliver
) :: :ok | :error

This method emits an effect on transition.

We send whole action data, because a different system will consume it straight from rabbitmq.

Link to this function

exchange_for(org, atom1, atom2)

Link to this function

maybe_rank_supporter(changeset, arg2, arg3)

Rank supporter when entering:

  1. supporter confirm stage
  2. action delivery stage
Link to this function

process(action)

Specs

process(
  action :: %Proca.Action{
    __meta__: term(),
    action_page: term(),
    action_page_id: term(),
    action_type: term(),
    campaign: term(),
    campaign_id: term(),
    donation: term(),
    fields: term(),
    id: term(),
    inserted_at: term(),
    messages: term(),
    processing_status: term(),
    ref: term(),
    source: term(),
    source_id: term(),
    supporter: term(),
    supporter_id: term(),
    testing: term(),
    updated_at: term(),
    with_consent: term()
  }
) :: :ok
Link to this function

process_async(action)

Link to this function

routing_for(map)

Link to this function

start_link(opts)

A noop sync method that lets you make sure all previous async messages were processed (used in testing)

Link to this function

transition(action, arg2)

Specs

transition(
  %Proca.Action{
    __meta__: term(),
    action_page: term(),
    action_page_id: term(),
    action_type: term(),
    campaign: term(),
    campaign_id: term(),
    donation: term(),
    fields: term(),
    id: term(),
    inserted_at: term(),
    messages: term(),
    processing_status: term(),
    ref: term(),
    source: term(),
    source_id: term(),
    supporter: term(),
    supporter_id: term(),
    testing: term(),
    updated_at: term(),
    with_consent: term()
  },
  %Proca.ActionPage{
    __meta__: term(),
    campaign: term(),
    campaign_id: term(),
    config: term(),
    delivery: term(),
    extra_supporters: term(),
    id: term(),
    inserted_at: term(),
    live: term(),
    locale: term(),
    name: term(),
    org: term(),
    org_id: term(),
    supporter_confirm_template: term(),
    thank_you_template: term(),
    updated_at: term()
  }
) ::
  :ok
  | {Ecto.Changeset.t(%Proca.Action{
       __meta__: term(),
       action_page: term(),
       action_page_id: term(),
       action_type: term(),
       campaign: term(),
       campaign_id: term(),
       donation: term(),
       fields: term(),
       id: term(),
       inserted_at: term(),
       messages: term(),
       processing_status: term(),
       ref: term(),
       source: term(),
       source_id: term(),
       supporter: term(),
       supporter_id: term(),
       testing: term(),
       updated_at: term(),
       with_consent: term()
     }), :action | :supporter, :confirm | :deliver}
  | {Ecto.Changeset.t(%Proca.Action{
       __meta__: term(),
       action_page: term(),
       action_page_id: term(),
       action_type: term(),
       campaign: term(),
       campaign_id: term(),
       donation: term(),
       fields: term(),
       id: term(),
       inserted_at: term(),
       messages: term(),
       processing_status: term(),
       ref: term(),
       source: term(),
       source_id: term(),
       supporter: term(),
       supporter_id: term(),
       testing: term(),
       updated_at: term(),
       with_consent: term()
     }), nil, nil}

This function implements the state machine for Action. It returns a changeset to update action/supporter (state) and atoms telling where to route action.