facade

package
v0.0.17 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 16, 2026 License: MIT Imports: 35 Imported by: 0

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:

  1. Initialize() - Validates dependencies and sets up internal state (called once via sync.Once)
  2. SetContainer() - Injects the IOC container for dynamic service resolution
  3. Start(ctx) - Opens database, starts CAT service, launches worker goroutines
  4. 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

View Source
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

type CountryLookupServiceInterface interface {
	Lookup(callsign string) (types.Country, error)
}

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

func (s *Service) CatStatus() map[string]string

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

func (s *Service) CurrentSessionQsoSlice() ([]types.Qso, error)

CurrentSessionQsoSlice retrieves the list of QSOs associated with the current session ID from the database.

func (*Service) FetchCatStateValues

func (s *Service) FetchCatStateValues() (map[string]map[string]string, error)

FetchCatStateValues retrieves the cat state values from the ConfigService.

func (*Service) FetchUiConfig

func (s *Service) FetchUiConfig() (*types.UiConfig, error)

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

func (s *Service) ForwardSessionQsosByEmail(slice []types.Qso, recipientEmail string) error

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

func (s *Service) GetQsoById(id int64) (types.Qso, error)

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

func (s *Service) Initialize() error

Initialize sets up the Service instance by verifying required dependencies and initializing its state.

func (*Service) IsContestDuplicate

func (s *Service) IsContestDuplicate(callsign, band string) (bool, error)

IsContestDuplicate checks if a contest entry with the given callsign and band already exists in the current logbook.

func (*Service) LogQso

func (s *Service) LogQso(qso types.Qso) error

LogQso inserts a new QSO into the database.

func (*Service) NewQso

func (s *Service) NewQso(callsign string) (*types.Qso, error)

NewQso initializes a new QSO object with the given callsign.

func (*Service) OpenInBrowser

func (s *Service) OpenInBrowser(urlStr string) error

OpenInBrowser opens the specified URL in the default web browser using the service's context.

func (*Service) Ready

func (s *Service) Ready() error

Ready checks if the service is initialized and started, then enqueues initialization and read commands to the CatService.

func (*Service) SetContainer

func (s *Service) SetContainer(container *iocdi.Container) error

SetContainer sets the IOC container for the Service. Returns an error if the Service is uninitialized or the container is nil.

func (*Service) Start

func (s *Service) Start(ctx context.Context) error

Start begins the Service lifecycle by initializing dependencies, opening the database, and marking it as started.

func (*Service) Stop

func (s *Service) Stop() error

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

func (s *Service) TotalQsosByLogbookId(logbookId int64) (int64, error)

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.

func (*Service) UpdateQso

func (s *Service) UpdateQso(qso types.Qso) error

UpdateQso updates an existing QSO record in the database and logs the operation; validates input and service state.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL