Proca.Server.Processing (proca v3.0.2)

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.

We need:

  • supporter.confirming
  • supporter.confirmed
  • action.confirming
  • action.confirmed
  • action.delivered

XXX for MVP, we assume:

ActionPage does not require Supporter confirmation, supporter :new -> :accepted ActionPage does not require Action confirmation, goes from :new -> :accepted But it is pushed to delivery queue and chnaged to :delivered (after processing in Broadway?)

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

This method emits an effect on transition.

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(),
    processing_status: term(),
    ref: term(),
    source: term(),
    source_id: term(),
    supporter: term(),
    supporter_id: term(),
    updated_at: term(),
    with_consent: term()
  },
  :action | :supporter,
  :confirm | :deliver
) :: :ok | :error

This method emits an effect on transition.

If custom processing is enabled, 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

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(),
    processing_status: term(),
    ref: term(),
    source: term(),
    source_id: term(),
    supporter: term(),
    supporter_id: 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(),
    processing_status: term(),
    ref: term(),
    source: term(),
    source_id: term(),
    supporter: term(),
    supporter_id: 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(),
    thank_you_template_ref: 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(),
       processing_status: term(),
       ref: term(),
       source: term(),
       source_id: term(),
       supporter: term(),
       supporter_id: term(),
       updated_at: term(),
       with_consent: term()
     }), :action | :supporter, :confirm | :deliver}

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