Skip to main content

Local Scan Log Cache Documentation

This code implements a local in-memory cache for attendance scan logs, aiming to reduce database reads and improve performance.

LocalScanLog struct

type LocalScanLog struct {
wg sync.WaitGroup
mtx SafeMutex

UpdatedScanLog []string

ScanLog []entity.AttendanceLogTable
ScanLogRead bool
IndexedScanLog map[string]*entity.AttendanceLogTable
ScanLogMapped bool

CompanyID string
ScanLogStartDate string
ScanLogEndDate string

dao *daos.Dao
}
  • wg sync.WaitGroup: Used for waiting for asynchronous database operations.
  • mtx SafeMutex: A mutex for safe concurrent access to the cache. (The SafeMutex likely adds additional safety checks or features compared to a standard sync.Mutex.)
  • UpdatedScanLog []string: Stores IDs of scan logs that have been updated and need to be persisted to the database.
  • ScanLog []entity.AttendanceLogTable: A slice holding all the cached scan logs.
  • ScanLogRead bool: Indicates whether the scan logs have been read from the database.
  • IndexedScanLog map[string]*entity.AttendanceLogTable: A map indexing scan logs by their ID for faster access.
  • ScanLogMapped bool: Indicates whether the ScanLog has been mapped to the IndexedScanLog.
  • CompanyID string: The ID of the company for which scan logs are cached.
  • ScanLogStartDate string: The start date of the cached scan log range.
  • ScanLogEndDate string: The end date of the cached scan log range.
  • dao *daos.Dao: The PocketBase DAO for database interaction.

globalLocalScanLog variable

var globalLocalScanLog = LocalScanLog{}

A global instance of LocalScanLog, suggesting a singleton pattern.

Functions

NewScanLogCache(dao *daos.Dao, companyID, start, end string, read bool) *LocalScanLog

Creates a new LocalScanLog instance.

  • dao: The PocketBase DAO.
  • companyID: The company ID.
  • start: The start date for the cache.
  • end: The end date for the cache.
  • read: Boolean indicating whether to immediately read scan logs from the database.

GetGLobalLocalScanLog() *LocalScanLog

Returns a pointer to the global LocalScanLog instance.

SetDao(dao *daos.Dao) *LocalScanLog

Sets the DAO for the LocalScanLog instance.

GetDao() *daos.Dao

Returns the DAO associated with the LocalScanLog instance.

WaitFinishReadDB()

Waits for all asynchronous database read operations to complete.

InsertOne(scanLog entity.AttendanceLogTable) error

Inserts a new scan log into the cache and the database.

InsertToCache(scanLog entity.AttendanceLogTable)

Inserts a scan log into the local cache.

UpdateDB() error

Updates the database with any changes made to the cached scan logs.

ResetScanLog()

Clears the cache.

IsDateInCache(calcDate string) bool

Checks if a given date is within the cached date range.

IsDateRangeInCache(start, end string) bool

Checks if a given date range is within the cached date range.

IsDateRangeInCacheTime(start, end time.Time) bool

Checks if a given date range (as time.Time objects) is within the cached date range.

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

Refreshes the cache if the provided parameters don't match the current cache or if force is true.

ReadAllScanLogs(companyID, startDate, endDate string)

Reads all scan logs for a given company and date range from the database and populates the cache. It expands the date range by one day on both sides to accommodate overnight shifts.

GetScanLogsForOnePersonOneDate(userID, calcDate string) []*entity.AttendanceLogTable

Retrieves scan logs for a specific user on a specific date from the cache.

GetScanLogsForOnePersonOneDatePlus(userID, calcDate string) []*entity.AttendanceLogTable

Retrieves scan logs for a specific user on a date, including the day before and after, to handle overnight shifts. It filters out logs already marked as UsedAsWinner.

GetScanLogsForOnePersonOneDatePlusDuringDuration(userID, calcDate string, duration float64) []*entity.AttendanceLogTable

Similar to GetScanLogsForOnePersonOneDatePlus, but also considers a specified duration beyond the end of the day.

GetScanLogsForOnePersonDateRange(userID string, startDate, endDate time.Time) []*entity.AttendanceLogTable

Retrieves scan logs for a specific user within a given date range (as time.Time objects).

Improvements and Considerations

  • Error Handling: Some functions, especially the asynchronous ReadAllScanLogs, could improve error handling by returning errors instead of just logging them. This would allow calling functions to handle errors more gracefully.
  • Cache Invalidation: The cache currently doesn't have an automatic invalidation mechanism. Consider adding logic to invalidate and refresh the cache based on time or events (e.g., new scan logs being added to the database).
  • Singleton Pattern: Evaluate whether the singleton pattern (globalLocalScanLog) is the most appropriate design. Dependency injection might provide more flexibility and testability.
  • SafeMutex: The documentation should clarify what additional features or safety mechanisms SafeMutex provides compared to a standard sync.Mutex.
  • UpdatedScanLog Handling: The logic for handling UpdatedScanLog could be more robust. If UpdateDB fails partially, it's unclear how the remaining updates are handled. Consider using a more sophisticated mechanism for tracking and retrying failed updates.
  • Documentation for UsedAsWinner: The documentation should explain the purpose and usage of the UsedAsWinner flag in the AttendanceLogTable struct.

This revised documentation provides a more detailed explanation of the LocalScanLog cache, including its structure, functionality, and potential areas for improvement. This should help developers understand and use the cache effectively. Remember to address the suggested improvements for a more robust and maintainable implementation.