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. (TheSafeMutex
likely adds additional safety checks or features compared to a standardsync.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 theScanLog
has been mapped to theIndexedScanLog
.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 mechanismsSafeMutex
provides compared to a standardsync.Mutex
.UpdatedScanLog
Handling: The logic for handlingUpdatedScanLog
could be more robust. IfUpdateDB
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 theUsedAsWinner
flag in theAttendanceLogTable
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.