Skip to content

Refactoring Sync

I would like to refactor sync!

First some terms. This is the member state state-machine. The goal is to have as few unique transitions as possible. If two actions can be done by the same transition, even better...

waiting --[join]--> active  ---[pause   ]---> inactive  --[exit]--> terminated --[cleanup]--> 0
                           <---[activate]---
                           <--------------------[activate]-------

If some attribute except state changes we have an attribute_changed event.

To find out which transition we do, we add a last_state to the user. Then the sync logic is:

enum SyncState { Unchanged, Updated, Error }

// Functions must be idempotent!
// I.g. if the member is already in the desired state they should return Unchanged.
interface SyncAdapter {
  ensure_created(member) : SyncState
  ensure_active(member) : SyncState
  ensure_inactive(member) : SyncState
  ensure_terminated(member) : SyncState
  ensure_updated(member) : SyncState
  ensure_deleted(member) : SyncState
}

get_transition(old_state, new_state) : Transition = /* see above state machine */

sync_member(transition, adapter, member) : SyncState =
  transition.match
    case join:
      if adapter.ensure_created(member) != kError
        adapter.ensure_active(member)
    case activate:
      adapter.ensure_active(member)
    case pause
      adapter.ensure_inactive(member)
    case terminate:
      adapter.ensure_terminated(member)
    case cleanup:
      adapter.ensure_deleted(member)
    case attribute_changed:
      adapter.ensure_updated(member)

sync_members(members, adapters) :
  members.each member =>
    if member.last_sync < member.last_change
      transition = get_transition(member.last_state, member.state)
      bool update = false
      adapters.each adapter =>
        sync_member(transition, adapter, member).match
          case Updated:
            update = true
          case Error:
            update = false
            break
          case Unchanged:
            continue
      if update
        if transition == delete
          member.delete
        else
          member.last_state = member.state
          member.last_sync = now
          member.update

What do you think?