Documentation
¶
Overview ¶
Package facade provides the backend service layer for the Station Manager logging application.
Overview ¶
The facade package implements the Facade design pattern, providing a unified interface between the Wails frontend (JavaScript/TypeScript) and the various backend services. It acts as the single entry point for all frontend operations, coordinating multiple subsystems while hiding their complexity from the UI layer.
Architecture ¶
The Service struct is the central component, registered with Wails for frontend binding. It orchestrates the following subsystems:
- ConfigService: Application configuration management
- LoggerService: Structured logging
- DatabaseService: SQLite database operations (QSOs, logbooks, contacts)
- CatService: Radio CAT (Computer Aided Transceiver) control
- HamnutLookupService: Callsign lookup via HamQTH
- QrzLookupService: Callsign lookup via QRZ.com
- EmailService: ADIF file forwarding via email
- Forwarders: QSO upload to online services (QRZ.com logbook, etc.)
Lifecycle ¶
The facade follows a strict lifecycle:
- Initialize() - Validates dependencies and sets up internal state (called once via sync.Once)
- SetContainer() - Injects the IOC container for dynamic service resolution
- Start(ctx) - Opens database, starts CAT service, launches worker goroutines
- Stop() - Gracefully shuts down workers, closes database, cleans up resources
Concurrency Model ¶
The facade manages several concurrent subsystems:
- CAT Status Listener: Receives radio status updates and emits events to the frontend
- QSO Forwarding Workers: Pool of workers that upload QSOs to online services
- DB Write Worker: Serializes all database writes to prevent SQLite busy errors
- Polling Loop: Periodically checks for pending QSO uploads
All workers respond to context cancellation and shutdown signals for graceful termination.
Frontend Integration ¶
Methods on the Service struct are automatically bound to the frontend via Wails. The frontend can call these methods directly:
- FetchUiConfig() - Get UI configuration
- NewQso(callsign) - Initialize a new QSO with callsign lookup
- LogQso(qso) - Save a QSO to the database
- UpdateQso(qso) - Update an existing QSO
- Ready() - Signal that the UI is ready to receive CAT updates
Events are emitted to the frontend using Wails runtime.EventsEmit for real-time updates (e.g., radio frequency/mode changes).
Validation ¶
QSO data is validated using go-playground/validator with custom validators for:
- Amateur radio bands (e.g., "20m", "40m")
- Operating modes (e.g., "SSB", "CW")
- ADIF date format (YYYYMMDD)
- ADIF time format (HHMM or HHMMSS)
- RST signal reports
- Frequency in MHz
Error Handling ¶
The package uses the custom errors package for operation tracing. Each function defines an errors.Op constant for the call chain. Errors returned to the frontend use errors.Root() to provide clean error messages without internal implementation details.
Example Usage ¶
The facade is typically instantiated via dependency injection:
container := iocdi.New() container.Register(facade.ServiceName, reflect.TypeOf((*facade.Service)(nil))) // ... register other services ... container.Build() svc, _ := container.ResolveSafe(facade.ServiceName) facade := svc.(*facade.Service) facade.SetContainer(container) facade.Start(ctx)
Index ¶
- Constants
- type CatServiceInterface
- type ConfigServiceInterface
- type CountryLookupServiceInterface
- type DatabaseServiceInterface
- type EmailServiceInterface
- type LookupServiceInterface
- type Service
- func (s *Service) CatStatus() map[string]string
- func (s *Service) CurrentSessionQsoSlice() ([]types.Qso, error)
- func (s *Service) FetchCatStateValues() (map[string]map[string]string, error)
- func (s *Service) FetchUiConfig() (*types.UiConfig, error)
- func (s *Service) ForwardSessionQsosByEmail(slice []types.Qso, recipientEmail string) error
- func (s *Service) GetQsoById(id int64) (types.Qso, error)
- func (s *Service) Initialize() error
- func (s *Service) IsContestDuplicate(callsign, band string) (bool, error)
- func (s *Service) LogQso(qso types.Qso) error
- func (s *Service) NewQso(callsign string) (*types.Qso, error)
- func (s *Service) OpenInBrowser(urlStr string) error
- func (s *Service) Ready() error
- func (s *Service) SetContainer(container *iocdi.Container) error
- func (s *Service) Start(ctx context.Context) error
- func (s *Service) Stop() error
- func (s *Service) TotalQsosByLogbookId(logbookId int64) (int64, error)
- func (s *Service) UpdateQso(qso types.Qso) error
Constants ¶
const (
ServiceName = "logging-app-facade"
)
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CatServiceInterface ¶ added in v0.0.12
type CatServiceInterface interface {
Start() error
Stop() error
EnqueueCommand(cmd interface{}) error
StatusChannel() (<-chan map[string]string, error)
RigConfig() types.RigConfig
}
CatServiceInterface defines the interface for CAT service operations.
type ConfigServiceInterface ¶ added in v0.0.12
type ConfigServiceInterface interface {
RequiredConfigs() (types.RequiredConfigs, error)
LoggingStationConfigs() (types.LoggingStation, error)
CatStateValues() (map[string]map[string]string, error)
ForwarderConfigs() ([]types.ForwarderConfig, error)
}
ConfigServiceInterface defines the interface for configuration operations.
type CountryLookupServiceInterface ¶ added in v0.0.12
CountryLookupServiceInterface defines the interface for country lookup services.
type DatabaseServiceInterface ¶ added in v0.0.12
type DatabaseServiceInterface interface {
Open() error
Close() error
Migrate() error
FetchLogbookByID(id int64) (types.Logbook, error)
GenerateSession() (int64, error)
InsertQso(qso types.Qso) (int64, error)
UpdateQso(qso types.Qso) error
FetchQsoById(id int64) (types.Qso, error)
FetchQsoSliceBySessionID(sessionID int64) ([]types.Qso, error)
FetchQsoSliceByCallsign(callsign string) ([]types.ContactHistory, error)
FetchQsoCountByLogbookId(logbookId int64) (int64, error)
InsertQsoUpload(qsoId int64, action interface{}, service interface{}) error
UpdateQsoUploadStatus(id int64, status interface{}, action interface{}, attempts int, errState string) error
FetchPendingUploads() ([]types.QsoUpload, error)
FetchContactedStationByCallsign(callsign string) (types.ContactedStation, error)
InsertContactedStation(station types.ContactedStation) (int64, error)
UpdateContactedStation(station types.ContactedStation) error
FetchCountryByCallsign(callsign string) (types.Country, error)
FetchCountryByName(name string) (types.Country, error)
InsertCountry(country types.Country) (int64, error)
UpdateCountry(country types.Country) error
IsContestDuplicateByLogbookID(logbookId int64, callsign string, band string) (bool, error)
SoftDeleteSessionByID(sessionID int64) error
BeginTxContext(ctx context.Context) (*sql.Tx, context.CancelFunc, error)
}
DatabaseServiceInterface defines the interface for database operations used by the facade. This allows for mocking in tests.
type EmailServiceInterface ¶ added in v0.0.12
type EmailServiceInterface interface {
BuildEmailWithADIFAttachment(subject, body, from string, to []string, qsos []types.Qso) (interface{}, error)
Send(mail interface{}) error
}
EmailServiceInterface defines the interface for email operations.
type LookupServiceInterface ¶ added in v0.0.12
type LookupServiceInterface interface {
Lookup(callsign string) (types.ContactedStation, error)
}
LookupServiceInterface defines the interface for callsign lookup services.
type Service ¶
type Service struct {
ConfigService *config.Service `di.inject:"configservice"`
LoggerService *logging.Service `di.inject:"loggingservice"`
DatabaseService *sqlite.Service `di.inject:"sqliteservice"`
CatService *cat.Service `di.inject:"catservice"`
HamnutLookupService *hamnut.Service `di.inject:"hamnutlookupservice"`
QrzLookupService *qrz.Service `di.inject:"qrzlookupservice"`
EmailService *email.Service `di.inject:"emailservice"`
CurrentLogbook types.Logbook
// contains filtered or unexported fields
}
func (*Service) CatStatus ¶
CatStatus returns nil and is defined only to export the method signature. NOTE: the return type is not types.CatStatus, because this type would not be understood by the frontend.
func (*Service) CurrentSessionQsoSlice ¶
CurrentSessionQsoSlice retrieves the list of QSOs associated with the current session ID from the database.
func (*Service) FetchCatStateValues ¶
FetchCatStateValues retrieves the cat state values from the ConfigService.
func (*Service) FetchUiConfig ¶
FetchUiConfig retrieves the UI configuration object. It returns an error if the service is not initialized, or the underlying ConfigService returns an error.
func (*Service) ForwardSessionQsosByEmail ¶
ForwardSessionQsosByEmail forwards a slice of QSOs to the specified email address as an ADIF attachment. Returns an error if the service is uninitialized, not started, input is invalid, or operation fails.
func (*Service) GetQsoById ¶
GetQsoById retrieves a QSO record by its ID from the database. Returns an error if the service is not ready or ID is invalid.
func (*Service) Initialize ¶
Initialize sets up the Service instance by verifying required dependencies and initializing its state.
func (*Service) IsContestDuplicate ¶
IsContestDuplicate checks if a contest entry with the given callsign and band already exists in the current logbook.
func (*Service) OpenInBrowser ¶
OpenInBrowser opens the specified URL in the default web browser using the service's context.
func (*Service) Ready ¶
Ready checks if the service is initialized and started, then enqueues initialization and read commands to the CatService.
func (*Service) SetContainer ¶
SetContainer sets the IOC container for the Service. Returns an error if the Service is uninitialized or the container is nil.
func (*Service) Start ¶
Start begins the Service lifecycle by initializing dependencies, opening the database, and marking it as started.
func (*Service) Stop ¶
Stop gracefully shuts down the service, closes resources, and resets the service state. Returns an error if critical failures occur during shutdown, but attempts to complete all shutdown steps regardless of individual failures.
func (*Service) TotalQsosByLogbookId ¶
TotalQsosByLogbookId retrieves the total number of QSOs for the specified logbook ID. Returns the count of QSOs and an error if the service is not initialized, started, or the logbook ID is invalid.