Skip to main content

Local Calendar Schedule Cache Documentation

This code implements a local in-memory cache for calendar schedules and their details, designed to optimize performance by minimizing database interactions.

LocalCalendarSchedule struct

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

NeedUpdateCalendarSchedules []string
NeedUpdateCalendarScheduleDetails []string

CalendarSchedules []entity.CalendarScheduleTable
IndexedCalendarSchedule map[string]*entity.CalendarScheduleTable
CalendarSchedulesRead bool
DetailsRead bool
MappedByCalendarScheduleID bool
MappedByUserID bool
CalendarScheduleDetails []entity.CalendarScheduleDetailsTable
IndexedCalendarScheduleDetails map[string]*entity.CalendarScheduleDetailsTable
MapDetailsByCalendarScheduleID map[string][]*entity.CalendarScheduleDetailsTable

CalendarSchedulesByPerson map[string]map[string][]*entity.CalendarScheduleTable

CompanyID string
Start string
End string
}

  • wg sync.WaitGroup: Manages asynchronous database operations.
  • mtx SafeMutex: Ensures thread-safe access to the cache. (Likely adds safety checks compared to a standard mutex.)
  • dao *daos.Dao: The PocketBase DAO.
  • NeedUpdateCalendarSchedules []string: IDs of calendar schedules that need updating in the database.
  • NeedUpdateCalendarScheduleDetails []string: IDs of calendar schedule details that need updating.
  • CalendarSchedules []entity.CalendarScheduleTable: Slice of calendar schedules.
  • IndexedCalendarSchedule map[string]*entity.CalendarScheduleTable: Calendar schedules indexed by ID.
  • CalendarSchedulesRead bool: Indicates if calendar schedules have been read from the database.
  • DetailsRead bool: Indicates if details have been read.
  • MappedByCalendarScheduleID bool: Indicates if details are mapped by calendar schedule ID.
  • MappedByUserID bool: Indicates if details are mapped by user ID (though this mapping doesn't seem to be used in the current code).
  • CalendarScheduleDetails []entity.CalendarScheduleDetailsTable: Slice of calendar schedule details.
  • IndexedCalendarScheduleDetails map[string]*entity.CalendarScheduleDetailsTable: Details indexed by ID.
  • MapDetailsByCalendarScheduleID map[string][]*entity.CalendarScheduleDetailsTable: Details mapped by calendar schedule ID.
  • CalendarSchedulesByPerson map[string]map[string][]*entity.CalendarScheduleTable: Schedules organized by person and date. map[UserProfileID][Date] -> []*CalendarScheduleTable.
  • CompanyID string: The company ID for which data is cached.
  • Start string: The start date of the cached range.
  • End string: The end date of the cached range.

globalCalendarSchedule Variable

var globalCalendarSchedule = LocalCalendarSchedule{}

A global instance of LocalCalendarSchedule (singleton pattern).

Functions

NewCalendarScheduleCache(dao *daos.Dao, companyID, start, end string, read bool) *LocalCalendarSchedule

Creates a new LocalCalendarSchedule instance.

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

GetGlobalCalendarSchedules() *LocalCalendarSchedule

Returns the global LocalCalendarSchedule instance.

SetDao(dao *daos.Dao) *LocalCalendarSchedule

Sets the DAO for the instance.

LoadCalendarSchedules()

Loads calendar schedules into a map (CalendarSchedulesByPerson) organized by user ID and date.

GetDao() *daos.Dao

Gets the DAO for the instance.

WaitFinishReadDB()

Waits for asynchronous database operations to complete.

InsertToCache(calSched *entity.CalendarScheduleTable)

Inserts a calendar schedule and its details into the cache. Assumes the calSched and its details have already been saved to the database (so they have IDs).

deleteDetailByID(id string) int

Deletes a calendar schedule detail from the cache by its ID.

remapDetails()

Rebuilds the maps that index and organize calendar schedule details.

remapCalendarSchedule()

Rebuilds the map that indexes calendar schedules and assigns details to them.

UpdateCache(calSched *entity.CalendarScheduleTable)

Updates a calendar schedule in the cache. This function handles the logic for updating existing details (marking them as deleted) and adding new details.

UpsertOne(calSched *entity.CalendarScheduleTable, details bool) error

Upserts (inserts or updates) a calendar schedule and its details in both the database and the cache.

SyncWithDB(details bool) error

Synchronizes the cached calendar schedules and details (marked for update) with the database.

ResetMaps(schedule, detail bool)

Clears the specified cache maps (schedules and/or details).

ReadAgain(companyID, start, end string, force bool) *LocalCalendarSchedule

Reloads data from the database if force is true, if the date range is outside the cached range, or if the companyID has changed.

ReadAllWithDetails(companyID string, start string, end string)

Reads all calendar schedules and their details from the database for the specified company and date range, populating the cache.

DebugPrint(id string)

Prints debugging information about the cached calendar schedules.

IsDateInCache(calcDate string) bool

Checks if a date is within the cached date range.

IsDateRangeInCache(start, end string) bool

Checks if a date range is within the cached range.

FindCalendarScheduleIDByDateString(calcDate string) string

Finds a calendar schedule ID by date.

CheckUnMatchedCalendarSchedule()

Checks for inconsistencies between calendar schedules and their details in the cache (for debugging).

FindCalendarSchedulesByPersonByDate(person, calcDate string) *entity.CalendarScheduleTable

Retrieves a calendar schedule by person and date.

FindCalendarSchedulesByPersonByDateRange(person, startDate, endDate string) []*entity.CalendarScheduleTable

Retrieves calendar schedules for a person within a date range.

FindCalendarSchedulesByCompanyByDateRange(companyID, startDate, endDate string) []*entity.CalendarScheduleTable

Retrieves calendar schedules for a company within a date range.

NeedToSaveSchedules() bool, NumberCalendarSchedulesNeedUpdated() int, NeedToSaveCalendarScheduleDetails() bool, NumberCalendarScheduleDetailsNeedUpdated() int, AddCalendarScheduleIDToUpdateLater(id string)

Functions related to tracking which calendar schedules and details need to be saved/updated in the database.

DebugChange(), DebugChangeRevert()

Debugging functions to test updating calendar schedules in the cache.

Example Usage

dao := // ... obtain your PocketBase DAO
companyID := "your_company_id"
startDate := "2024-05-01"
endDate := "2024-05-31"


// Create a new CalendarScheduleCache and immediately read data
calendarScheduleCache := caching.NewCalendarScheduleCache(dao, companyID, startDate, endDate, true)


// Find schedules by person and date range
personSchedules := calendarScheduleCache.FindCalendarSchedulesByPersonByDateRange("user_id_123", "2024-05-10", "2024-05-15")

// Find schedules by company and date range
companySchedules := calendarScheduleCache.FindCalendarSchedulesByCompanyByDateRange(companyID, startDate, endDate)


// Upsert a new calendar schedule
newSchedule := &entity.CalendarScheduleTable{
// ... set schedule fields
}
err := calendarScheduleCache.UpsertOne(newSchedule, true) // true to upsert details as well

// Force a cache refresh
calendarScheduleCache.ReadAgain(companyID, startDate, endDate, true)

Improvements and Considerations

  • Error Handling: Improve error handling in functions like ReadAllWithDetails and SyncWithDB by returning errors instead of just logging them.
  • Cache Invalidation: Implement a proper cache invalidation strategy (time-based or event-driven) to ensure data consistency.
  • Singleton Pattern: Evaluate the use of the singleton pattern (globalCalendarSchedule). Dependency injection offers better testability and flexibility.
  • Unused MappedByUserID: Remove the MappedByUserID field if it's not being used.
  • SafeMutex: Clearly document the additional safety mechanisms of SafeMutex.
  • Code Clarity and Comments: Improve code comments to explain complex logic more clearly, particularly in the UpdateCache function.
  • Locking Granularity: Finer-grained locking (e.g., separate mutexes for schedules and details) could improve concurrency.

This comprehensive documentation provides a detailed understanding of the LocalCalendarSchedule cache and its functionalities. By addressing the suggested improvements, you can create a more robust and maintainable caching solution.