- Create modular architecture with separate packages for config, database, HTTP, logging, and state management - Implement Cobra CLI with daemon command - Set up Uber FX dependency injection - Add Chi router with health check and IP lookup endpoints - Implement GeoIP database downloader with automatic updates - Add state persistence for tracking database download times - Include comprehensive test coverage for all components - Configure structured logging with slog - Add Makefile with test, lint, and build targets - Support both IPv4 and IPv6 lookups - Return country, city, ASN, and location data in JSON format
72 lines
1.5 KiB
Go
72 lines
1.5 KiB
Go
package ipapi
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
|
|
"git.eeqj.de/sneak/ipapi/internal/config"
|
|
"git.eeqj.de/sneak/ipapi/internal/database"
|
|
"git.eeqj.de/sneak/ipapi/internal/http"
|
|
"git.eeqj.de/sneak/ipapi/internal/state"
|
|
"go.uber.org/fx"
|
|
)
|
|
|
|
// Options contains all dependencies for IPAPI.
|
|
type Options struct {
|
|
fx.In
|
|
|
|
Config *config.Config
|
|
Logger *slog.Logger
|
|
State *state.Manager
|
|
Database *database.Manager
|
|
Server *http.Server
|
|
}
|
|
|
|
// IPAPI is the main application structure.
|
|
type IPAPI struct {
|
|
config *config.Config
|
|
logger *slog.Logger
|
|
state *state.Manager
|
|
database *database.Manager
|
|
server *http.Server
|
|
}
|
|
|
|
// New creates a new IPAPI instance with the given options.
|
|
func New(opts Options) *IPAPI {
|
|
return &IPAPI{
|
|
config: opts.Config,
|
|
logger: opts.Logger,
|
|
state: opts.State,
|
|
database: opts.Database,
|
|
server: opts.Server,
|
|
}
|
|
}
|
|
|
|
// Start initializes and starts all components.
|
|
func (i *IPAPI) Start(ctx context.Context) error {
|
|
i.logger.Info("Starting IP API daemon",
|
|
"port", i.config.Port,
|
|
"state_dir", i.config.StateDir,
|
|
)
|
|
|
|
// Initialize state
|
|
if err := i.state.Initialize(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Download databases if needed
|
|
if err := i.database.EnsureDatabases(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Start HTTP server
|
|
return i.server.Start(ctx)
|
|
}
|
|
|
|
// Stop gracefully shuts down all components.
|
|
func (i *IPAPI) Stop(ctx context.Context) error {
|
|
i.logger.Info("Stopping IP API daemon")
|
|
|
|
return i.server.Stop(ctx)
|
|
}
|