From ba28a02302759867e299350a91822e6eb1c4ad41 Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Tue, 6 Feb 2024 10:52:18 +0100 Subject: [PATCH] Allow manual specification of filewatcher behavior (#29) --- cmd/localstack/awsutil.go | 4 ++-- cmd/localstack/filenotify/filenotify.go | 20 +++++++++++++++++--- cmd/localstack/hotreloading.go | 4 ++-- cmd/localstack/main.go | 4 +++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/cmd/localstack/awsutil.go b/cmd/localstack/awsutil.go index de18378..7fa02c4 100644 --- a/cmd/localstack/awsutil.go +++ b/cmd/localstack/awsutil.go @@ -156,14 +156,14 @@ func RunDNSRewriter(opts *LsOpts, ctx context.Context) { log.Debugln("DNS server stopped") } -func RunHotReloadingListener(server *CustomInteropServer, targetPaths []string, ctx context.Context) { +func RunHotReloadingListener(server *CustomInteropServer, targetPaths []string, ctx context.Context, fileWatcherStrategy string) { if len(targetPaths) == 1 && targetPaths[0] == "" { log.Debugln("Hot reloading disabled.") return } defaultDebouncingDuration := 500 * time.Millisecond log.Infoln("Hot reloading enabled, starting filewatcher.", targetPaths) - changeListener, err := NewChangeListener(defaultDebouncingDuration) + changeListener, err := NewChangeListener(defaultDebouncingDuration, fileWatcherStrategy) if err != nil { log.Errorln("Hot reloading disabled due to change listener error.", err) return diff --git a/cmd/localstack/filenotify/filenotify.go b/cmd/localstack/filenotify/filenotify.go index 1c1d708..579a76a 100644 --- a/cmd/localstack/filenotify/filenotify.go +++ b/cmd/localstack/filenotify/filenotify.go @@ -38,14 +38,28 @@ func shouldUseEventWatcher() bool { } // New tries to use a fs-event watcher, and falls back to the poller if there is an error -func New(interval time.Duration) (FileWatcher, error) { +func New(interval time.Duration, fileWatcherStrategy string) (FileWatcher, error) { + if fileWatcherStrategy != "" { + log.Debugln("Forced usage of filewatcher strategy: ", fileWatcherStrategy) + if fileWatcherStrategy == "event" { + if watcher, err := NewEventWatcher(); err == nil { + return watcher, nil + } else { + log.Fatalln("Event based filewatcher is selected, but unable to start. Please try setting the filewatcher to polling. Error: ", err) + } + } else if fileWatcherStrategy == "polling" { + return NewPollingWatcher(interval), nil + } else { + log.Fatalf("Invalid filewatcher strategy %s. Only event and polling are allowed.\n", fileWatcherStrategy) + } + } if shouldUseEventWatcher() { if watcher, err := NewEventWatcher(); err == nil { - log.Debugln("Using event based filewatcher") + log.Debugln("Using event based filewatcher (autodetected)") return watcher, nil } } - log.Debugln("Using polling based filewatcher") + log.Debugln("Using polling based filewatcher (autodetected)") return NewPollingWatcher(interval), nil } diff --git a/cmd/localstack/hotreloading.go b/cmd/localstack/hotreloading.go index 9218465..a0c4467 100644 --- a/cmd/localstack/hotreloading.go +++ b/cmd/localstack/hotreloading.go @@ -16,8 +16,8 @@ type ChangeListener struct { watchedFolders []string } -func NewChangeListener(debouncingInterval time.Duration) (*ChangeListener, error) { - watcher, err := filenotify.New(200 * time.Millisecond) +func NewChangeListener(debouncingInterval time.Duration, fileWatcherStrategy string) (*ChangeListener, error) { + watcher, err := filenotify.New(200*time.Millisecond, fileWatcherStrategy) if err != nil { log.Errorln("Cannot create change listener due to filewatcher error.", err) return nil, err diff --git a/cmd/localstack/main.go b/cmd/localstack/main.go index 02bf247..e6eb026 100644 --- a/cmd/localstack/main.go +++ b/cmd/localstack/main.go @@ -21,6 +21,7 @@ type LsOpts struct { User string CodeArchives string HotReloadingPaths []string + FileWatcherStrategy string EnableDnsServer string LocalstackIP string InitLogLevel string @@ -52,6 +53,7 @@ func InitLsOpts() *LsOpts { // optional or empty CodeArchives: os.Getenv("LOCALSTACK_CODE_ARCHIVES"), HotReloadingPaths: strings.Split(GetenvWithDefault("LOCALSTACK_HOT_RELOADING_PATHS", ""), ","), + FileWatcherStrategy: os.Getenv("LOCALSTACK_FILE_WATCHER_STRATEGY"), EnableDnsServer: os.Getenv("LOCALSTACK_ENABLE_DNS_SERVER"), EnableXRayTelemetry: os.Getenv("LOCALSTACK_ENABLE_XRAY_TELEMETRY"), LocalstackIP: os.Getenv("LOCALSTACK_HOSTNAME"), @@ -230,7 +232,7 @@ func main() { if err != nil { log.Fatalln(err) } - go RunHotReloadingListener(interopServer, lsOpts.HotReloadingPaths, fileWatcherContext) + go RunHotReloadingListener(interopServer, lsOpts.HotReloadingPaths, fileWatcherContext, lsOpts.FileWatcherStrategy) // start runtime init. It is important to start `InitHandler` synchronously because we need to ensure the // notification channels and status fields are properly initialized before `AwaitInitialized`