Skip to main content
Services around the game

Not translated yet — showing English.

Social

Social adds one concept: a relationship of two actors, with a state of its own and an initiator. A clan, a guild or a squad is a group with a relationship layer over it, not a second kind of thing; and blocking, which several modules need, lives here so that only one place owns it.

When to use it

  • Players need each other by name: friends, followers, block lists.
  • A clan or guild needs entry rules: an invitation from the group, a join request from an actor, and a decision on either.
  • A friend list has to show who is online: presence is derived from sessions, and who may see it is a predicate you declare.
  • Another module needs to know somebody is blocked: it reads that state from here rather than keeping its own.
  • Skip it when the thing is a set of actors rather than a pair with a state: that is a group, and a group per pair would mean millions of two-person groups, each with its own lifecycle and entry rules.

Who does what

ActorCanCannot
playerpropose a relationship or follow; accept, decline or withdraw; break a mutual one; block and unblock; read their own relationships and the presence of related actors; subscribe to changes; submit a join requestread anyone else's list of relationships, under any participant relationship whatsoever
moderatordecide on invitations and join requests where they hold the membership-administration atomdecide on an intent they hold no permission for — that answers forbidden

The model

What a relationship declaration carries.

DeclaresWhat it is
kindsymmetric — the pair needs both sides to agree, and the state machine below is about it; or one-sided — following, whose only state is active. Uniqueness per pair and the idempotency of a proposal hold for both
re-invitation ruleafter a refusal: forbidden · permitted after a declared period · permitted at once. Declared, because "ask again" is a product decision
presence visibilitya predicate — to everyone · only to mutually connected · to nobody. There is no default
joining mode (on the group type)open · by request with a decision · by invitation only
retention of declined and brokenafter the declared period the relationship is removed, and re-inviting becomes possible again regardless of the re-invitation rule

The states of a symmetric relationship.

StateMeaning
proposedthe initiator proposed and the other side has not answered
mutualboth sides agree
declinedthe other side refused. The relationship is kept, because the re-invitation rule needs to know
brokenone side left a mutual relationship
blockedone side blocked the other

What is true of every relationship.

AlwaysWhat it is
one entity per pairnot two mirrored records. "A proposed to B" and "B was proposed to by A" are one fact read from two sides
an initiatoris declared: who proposed, which display and the re-invitation rule both need
blocked dominatesfrom it there is no transition to proposed or mutual
a blockis asymmetric in control, symmetric in effect: only the one who set it may lift it, and it acts both ways
the block stateis owned here and consumed elsewhere: messaging and others read it; none of them mutates it, and none keeps a copy
presenceis derived from sessions: not written by anybody, and the visibility predicate is applied per requester rather than once per actor
a deferred intentdoes not occupy a seat: an invitation or a join request never counts towards the group's capacity, so a hundred requests can't exhaust a clan of fifty
a groupkeeps an administrator: at least one actor must hold the membership-administration atom, and the last one cannot simply leave: a clan whose last administrator walked out could never admit anyone again
no intra-group roles"clan officer" is an actor holding an atom, not a rank stored in a list
an import never overwritesrelationships brought in from a login provider are additive: someone blocked does not become a friend because a provider says so

Errors

  • Already mutual is a conflict; there is nothing to propose.
  • A proposal to oneself is a validation refusal.
  • One of the sides has blocked answers not found — not forbidden, because a refusal that distinguished them would reveal the block. Repeating is pointless.
  • A re-invitation before the deadline is a conflict, worth repeating after it.
  • A limit exhausted — relationships, intents — is a conflict, not forbidden: the permission is held, but there is no capacity left. Retry once one frees up, or once the existing intents have been decided.
  • An expired intent is a conflict: create a new one rather than retrying the old.
  • The departure of a group's last administrator is a conflict until the permission has been handed on.
  • Deciding on someone else's intent without the permission answers forbidden, and repeating is pointless.
  • An import from a provider that is not connected answers unavailable: retry with backoff.

Limits

The numbers arrive with the platform limits chapter; what happens at each ceiling is fixed now.

  • Mutual relationships per actor: a proposal is refused as a conflict; existing ones are never broken to make room.
  • One-sided relationships per actor: a new one is refused; existing ones stay.
  • Outgoing proposals: a new one is refused, and there is no eviction: an evicted invitation would look like a declined one.
  • Blocks per actor: adding one is refused as a conflict, and older blocks are not evicted, so nobody is silently unblocked.
  • An intent's lifetime: expired, with an event.
  • The rate of proposals per actor: a rate limit with a deadline.
  • The rate of presence changes in the stream: bounded by the update rate rather than by discarding changes.
  • Retention of declined and broken relationships: removal by the declared period.