Skip to main content

Local Setting Cache Documentation

This code implements a local in-memory cache for rounding settings and company settings to improve performance by reducing database reads.

LocalSetting struct

type LocalSetting struct {
wg sync.WaitGroup
mtx sync.Mutex
dao *daos.Dao

IndexedRoundingSetting map[string]*entity.RoundingSettingTable
CompanySettings *entity.CompanyTable

AutoShifRule string
}
  • wg sync.WaitGroup: Used to wait for asynchronous database read operations to complete.
  • mtx sync.Mutex: Used to protect shared data during concurrent access (prevents race conditions).
  • dao *daos.Dao: A PocketBase DAO (Data Access Object) used to interact with the database.
  • IndexedRoundingSetting map[string]*entity.RoundingSettingTable: Stores rounding settings, indexed by a string key (likely the setting ID or a relevant identifier).
  • CompanySettings *entity.CompanyTable: Stores the settings for a specific company.
  • AutoShifRule string: Stores the autoshift rule for the company.

globalLocalSetting variable

var globalLocalSetting = LocalSetting{}

A global instance of the LocalSetting struct. This suggests a singleton pattern where this single instance is used throughout the application.

ReadAllSettings(companyId string) method

func (l *LocalSetting) ReadAllSettings(companyId string)

Reads all necessary settings from the database and populates the cache.

  • Takes the companyId as a parameter to retrieve company-specific settings.
  • Uses a mutex (l.mtx) to prevent race conditions during concurrent access.
  • Uses a wait group (l.wg) to ensure the asynchronous database reads complete before continuing.
  • Logs errors and informational messages using slog.
  • Reads rounding settings using queries.GetMappedRoundSetting.
  • Reads company settings using queries.GetCompanyById.
  • Caches the AutoshiftRule from the company settings, defaulting to "formula" if not set.

GetGlobalLocalSetting() function

func GetGlobalLocalSetting() *LocalSetting {
return &globalLocalSetting
}

Returns a pointer to the global LocalSetting instance.

SetDao(dao *daos.Dao) *LocalSetting method

func (l *LocalSetting) SetDao(dao *daos.Dao) *LocalSetting {
l.dao = dao
return l
}

Sets the DAO for the LocalSetting instance. This is crucial as it provides the means to interact with the database.

WaitFinishReadDB() method

func (l *LocalSetting) WaitFinishReadDB() {
l.wg.Wait()
}

Waits for all database read operations initiated by ReadAllSettings to complete.

NewRoundingSettingCache(dao *daos.Dao, read bool, companyId string) *LocalSetting function

func NewRoundingSettingCache(dao *daos.Dao, read bool, companyId string) *LocalSetting

Creates a new LocalSetting instance.

  • dao: The DAO to use for database interaction.
  • read: A boolean flag indicating whether to immediately read settings from the database.
  • companyId: The ID of the company for which to load settings.
  • If read is true, calls ReadAllSettings and WaitFinishReadDB to populate the cache synchronously.

Usage Example

dao := // ... get your PocketBase DAO
cache := caching.NewRoundingSettingCache(dao, true, "your_company_id")

// ... use cache.IndexedRoundingSetting, cache.CompanySettings, etc.

Improvements & Considerations

  • Error Handling: While errors are logged, they are not explicitly returned. Consider returning errors to allow calling functions to handle them appropriately.
  • Cache Invalidation: The current implementation doesn't have a mechanism for cache invalidation. If data changes in the database, the cache will become stale. Consider adding logic to refresh the cache periodically or on specific events.
  • Configuration: Hardcoding "formula" as the default AutoShifRule might be inflexible. Consider making this configurable.
  • Singleton vs. Instantiation: Evaluate if the singleton pattern (globalLocalSetting) is the best approach. Dependency injection might offer more flexibility and testability.

This documentation provides a comprehensive overview of the local setting cache implementation. By understanding its components and usage, you can effectively leverage it to optimize your application's performance. Remember to address the suggested improvements for a more robust and maintainable solution.