Skip to main content

Local Shifts Cache Documentation

This code implements a local in-memory cache for shifts, rules, breaks, and their relationships, aiming to speed up processing by reducing database reads.

LocalShifts Struct

type LocalShifts struct {
wg sync.WaitGroup
mtx SafeMutex
dao *daos.Dao

Shifts []entity.ShiftTable
ShiftsRead bool
IndexedShifts map[string]*entity.ShiftTable // key = shiftID
ShiftsMapped bool
ShiftsMapByShortLabel map[string]*entity.ShiftTable // Key = short_label
ShiftsMappedByShortLabel bool


Rules []entity.RuleTable
RulesRead bool
RulesMap map[string]*entity.RuleTable
RulesMapped bool

RuleUses []entity.RuleUseTable
RulesUseRead bool
RuleUsesMap map[string]*entity.RuleUseTable
RuleUsesMapped bool

RuleDetails []entity.RuleDetailTable
RulesDetailsRead bool
RuleDetailsMap map[string]*entity.RuleDetailTable
RulesDetailsMapped bool
RuleDetailsMapByRuleID map[string][]*entity.RuleDetailTable // key = rule_id
RulesDetailsMappedByRuleID bool

ShiftBreaks []entity.ShiftBreakTable
ShiftBreaksRead bool
ShiftBreakMap map[string]*entity.ShiftBreakTable
ShiftBreaksMapped bool

Breaks []entity.BreakTable
BreaksRead bool
BreaksMap map[string]*entity.BreakTable // key = breaks_id
BreaksMapped bool
BreaksMapByShiftID map[string][]*entity.BreakTable // key = shift_id
BreaksMappedByShiftID bool // already mapped


CompanyID string
}
  • wg sync.WaitGroup: Waits for asynchronous database operations.
  • mtx SafeMutex: A mutex for thread-safe access. (Likely adds safety checks beyond a standard mutex.)
  • dao *daos.Dao: The PocketBase DAO.
  • Shifts []entity.ShiftTable: Slice of all shifts.
  • ShiftsRead bool: Flag indicating if shifts have been read.
  • IndexedShifts map[string]*entity.ShiftTable: Shifts indexed by ID.
  • ShiftsMapped bool: Flag if shifts have been mapped to IndexedShifts.
  • ShiftsMapByShortLabel map[string]*entity.ShiftTable: Shifts indexed by short label.
  • ShiftsMappedByShortLabel bool: Flag if shifts have been mapped to ShiftsMapByShortLabel.
  • Rules, RulesRead, RulesMap, RulesMapped: Similar structure for rules.
  • RuleUses, RulesUseRead, RuleUsesMap, RuleUsesMapped: Similar structure for rule uses.
  • RuleDetails, RulesDetailsRead, RuleDetailsMap, RulesDetailsMapped, RuleDetailsMapByRuleID, RulesDetailsMappedByRuleID: Structure for rule details, including a map by rule ID.
  • ShiftBreaks, ShiftBreaksRead, ShiftBreakMap, ShiftBreaksMapped: Structure for shift breaks.
  • Breaks, BreaksRead, BreaksMap, BreaksMapped, BreaksMapByShiftID, BreaksMappedByShiftID: Structure for breaks, including a map by shift ID.
  • CompanyID string: The company ID.

globalLocalShifts variable

var globalLocalShifts = LocalShifts{}

A global instance of LocalShifts (singleton pattern).

Functions

NewShiftsCache(dao *daos.Dao, companyID string, read bool) *LocalShifts

Creates a new LocalShifts instance.

  • dao: The PocketBase DAO.
  • companyID: The company ID.
  • read: If true, reads data from the database immediately.

GetGlobalLocalShifts() *LocalShifts

Returns the global LocalShifts instance.

SetDao(dao *daos.Dao) *LocalShifts

Sets the DAO for the LocalShifts instance.

GetDao() *daos.Dao

Gets the DAO associated with the instance.

WaitFinishReadDB()

Waits for asynchronous database operations to complete.

ReadAgain(companyID string, force bool) *LocalShifts

Reads data from the database again if force is true or if data hasn't been read yet. Also reads again if the companyID has changed.

ReadAllShiftsWithRulesAndBreaks(companyID string)

Reads all shift-related data (shifts, rules, breaks, etc.) for the given companyID from the database and populates the cache. This function performs the database reads asynchronously and maps the relationships between shifts, rules, and breaks.

MapShiftsByShortLabel()

Creates a map of shifts keyed by their short labels if it hasn't already been created.

FindShiftByShortLabel(shortLabel string) *entity.ShiftTable

Finds a shift by its short label. Returns nil if not found.

GetShiftByID(shiftID string) *entity.ShiftTable

Retrieves a shift by its ID from the cache. Returns nil if not found.

GetAllShifts() []entity.ShiftTable

Returns all cached shifts. Reads from the database if the cache is empty.

FindShiftByID(shiftID string) *entity.ShiftTable

Finds a shift by its ID. Returns nil if not found. (This function seems redundant, as GetShiftByID does the same thing.)

Example Usage

dao := // ... obtain your PocketBase DAO
companyID := "your_company_id"

// Create a new ShiftsCache and read data immediately
shiftsCache := caching.NewShiftsCache(dao, companyID, true)

// Get all shifts
allShifts := shiftsCache.GetAllShifts()

// Find a shift by ID
shift := shiftsCache.GetShiftByID("shift_id_123")

// Find a shift by short label
shift := shiftsCache.FindShiftByShortLabel("SL-A")



// Force a cache refresh
shiftsCache.ReadAgain(companyID, true)

Improvements and Considerations

  • Error Handling: ReadAllShiftsWithRulesAndBreaks could benefit from returning errors instead of just logging them, allowing calling code to handle errors more gracefully.
  • Cache Invalidation: The cache currently lacks an invalidation mechanism. Implement time-based or event-driven invalidation to ensure data freshness.
  • Singleton Pattern: Evaluate the singleton pattern (globalLocalShifts). Dependency injection can provide better testability and flexibility.
  • Redundant FindShiftByID: Remove the seemingly redundant FindShiftByID function.
  • SafeMutex: Document the specific safety features provided by SafeMutex.
  • Locking Granularity: Consider more granular locking (e.g., separate mutexes for shifts, rules, and breaks) for improved concurrency.

This enhanced documentation provides a detailed overview of the LocalShifts cache and its functionalities. By understanding its structure and usage, developers can efficiently use the cache to optimize their application. Addressing the suggested improvements will further enhance the cache's robustness and maintainability.