Skip to content

Group & Submission Consistency

John DeNero edited this page Jan 13, 2015 · 1 revision

Invariants:

  • Every person is either not in a group, pending in exactly 1 group, or active in exactly 1 group.
  • Every group has at least 1 active member; empty groups are deleted.
  • Every group has at least 2 active or pending members; 1-person groups are deleted.

Permitted actions:

  • An active member can add a new pending member (make invitation).
  • A pending member can only accept or reject the invitation to join the group. (accept invitation) [A pending member cannot be invited to another group, create a group, or invite someone else to a group.]
  • An active member can remove a pending member (cancel invitation).
  • An active/pending member can leave a group (leave group or reject invitation).
  • A person not in a group can create a new group by adding a new pending member.
  • An active/pending member can see all active/pending members of the group.
  • An active member can see all active members' submissions.
  • An active member can select the final submission of the group.

Submissions:

  • Whenever a new active member is added to a group, the group final submission is updated to the most recent submission of any active member of the group.
  • Whenever the final submission of a person changes, that person should be notified with a link to the new final submission. This can occur because (a) they joined a group with a more recent final submission than theirs, or (b) someone else joined their group with a more recent final submission than the group's current final submission.

Enforcing invariants:

  • When inviting someone to a group, that invitation may fail because the target is already active/pending in another group, the group is too big, or the inviter is pending. A complete invitation transaction is:
    • [person A invites person B]
    • [concurrency lock A]
    • [check that A is not pending in any group]
    • [if A is not in a group, create group G_A with A as an active member]
    • [unlock A]
    • [concurrency lock G_A (group containing A)]
    • [check that G_A has capacity for another member]
    • [concurrency lock B]
    • [check that B is not pending or active]
    • [add B as pending member of G_A]
    • [unlock B]
    • [if G_A has only 1 member (because adding B failed), delete G_A]
    • [unlock G_A]
  • When B accepts an invitation to group G_A:
    • [concurrency lock G_A]
    • [check that B is a pending member of G_A]
    • [move B from pending to active in G_A]
    • [unlock G_A]
  • When A cancels an invitation to B for group G_A:
    • [concurrency lock B]
    • [concurrency lock G_A]
    • [check that B is a pending member of G_A]
    • [remove B from pending members of G_A]
    • [unlock G_A]
    • [unlock B]
  • When A rejects or leaves G_A:
    • [concurrency lock A]
    • [concurrency lock G_A]
    • [remove A from active and pending members of G_A]
    • [unlock G_A]
    • [unlock A]