Skip to main content

Identity Grains

Grains that manage user accounts, characters, sessions, and presence.

AccountGrain​

Global account state that persists across all seasons.

Key: Guid (userId/accountId)

State​

public class AccountGrainState
{
public Account? Account { get; set; }
public List<CharacterSummary> Characters { get; set; } = new();
}

Methods​

MethodDescription
GetAccountAsync()Get account info (creates if not exists)
GetCharactersAsync()Get all character summaries
CreateCharacterAsync()Create new character in a season
UpdateCharacterSummaryAsync()Update character summary after migration
UnlockCosmeticAsync()Unlock a cosmetic
UnlockAchievementAsync()Unlock an achievement
HasCosmeticAsync()Check if cosmetic is unlocked
HasAchievementAsync()Check if achievement is unlocked
ExistsAsync()Check if account has been created
DeleteAsync()Delete account (for testing)

Account Creation Flow​


CharacterGrain​

Per-season character state. Uses compound key for season isolation.

Key: Guid (characterId) + string (seasonId)

State​

public class CharacterGrainState
{
public Character? Character { get; set; }
public List<CharacterHistoryEntry> History { get; set; } = new();
}

Methods​

MethodDescription
InitializeAsync()Create new character
GetCharacterAsync()Get character details
AddExperienceAsync()Add XP (may level up)
SetStatAsync()Set a stat value
GetChallengeProgressAsync()Get challenge progress
UpdateChallengeProgressAsync()Update challenge progress
DieAsync()Kill character (triggers migration for HC)
GetHistoryAsync()Get character history
MigrateAsync()Migrate to new season

Hardcore Death Flow​


RefreshTokenGrain​

Manages JWT refresh tokens per user. Supports multiple devices and token rotation.

Key: Guid (userId)

State​

public class RefreshTokenState
{
public Dictionary<string, RefreshTokenInfo> Tokens { get; set; } = new();
}

Methods​

MethodDescription
CreateTokenAsync()Create new refresh token
ConsumeTokenAsync()Use and invalidate token (rotation)
RevokeTokenAsync()Revoke specific token
RevokeAllTokensAsync()Revoke all tokens (security)
CleanupExpiredAsync()Remove expired tokens

Token Rotation​


PlayerPresenceGrain​

Tracks online status and active connections. In-memory only (not persisted).

Key: Guid (userId)

State​

// In-memory only
private Dictionary<string, string> _connections = new(); // connectionId -> hubName

Methods​

MethodDescription
RegisterConnectionAsync()Add connection (returns true if first)
UnregisterConnectionAsync()Remove connection (returns true if last)
GetActiveConnectionsAsync()Get all active connections
IsOnlineAsync()Check if user is online

SessionLogGrain​

Persists session history for analytics and security.

Key: Guid (userId)

Methods​

MethodDescription
StartSessionAsync(ip)Log session start with IP
EndSessionAsync()Log session end
GetSessionHistoryAsync()Get session history