diff --git a/.trunk/configs/cspell.json b/.trunk/configs/cspell.json index 1880d952e..01e2ae1b8 100644 --- a/.trunk/configs/cspell.json +++ b/.trunk/configs/cspell.json @@ -44,6 +44,7 @@ "dsname", "dspc", "dynamicmap", + "embeddedpostgres", "embedder", "embedders", "envfiles", @@ -51,6 +52,7 @@ "euclidian", "expfmt", "fatih", + "fergusstrange", "fkey", "fnptr", "fptr", @@ -84,6 +86,7 @@ "idof", "iface", "Infof", + "iofs", "isatty", "isize", "jackc", diff --git a/.vscode/launch.json b/.vscode/launch.json index 3af94f38b..c311cea33 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,8 +10,7 @@ "env": { "FORCE_COLOR": "1", "MODUS_ENV": "dev", - "MODUS_DEBUG": "true", - "MODUS_DB": "postgresql://postgres:postgres@localhost:5433/my-runtime-db?sslmode=disable" // checkov:skip=CKV_SECRET_4 + "MODUS_DEBUG": "true" }, "args": [ "--refresh=1s", @@ -28,8 +27,7 @@ "env": { "FORCE_COLOR": "1", "MODUS_ENV": "dev", - "MODUS_DEBUG": "true", - "MODUS_DB": "postgresql://postgres:postgres@localhost:5433/my-runtime-db?sslmode=disable" // checkov:skip=CKV_SECRET_4 + "MODUS_DEBUG": "true" }, "args": ["--refresh=1s", "--appPath", "${input:appPath}"] }, @@ -46,8 +44,7 @@ "MODUS_DEBUG": "true", "AWS_REGION": "${input:awsRegion}", "AWS_PROFILE": "${input:awsProfile}", - "AWS_SDK_LOAD_CONFIG": "true", - "MODUS_DB": "postgresql://postgres:postgres@localhost:5433/my-runtime-db?sslmode=disable" // checkov:skip=CKV_SECRET_4 + "AWS_SDK_LOAD_CONFIG": "true" }, "args": [ "--useAwsStorage", diff --git a/CHANGELOG.md b/CHANGELOG.md index b008c0b95..dd28b2162 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ## UNRELEASED - fix: omit parallel_tool_calls in Go OpenAI SDK if it is set to true [#849](https://github.com/hypermodeinc/modus/pull/849) +- feat: use embedded postgres on Windows [#851](https://github.com/hypermodeinc/modus/pull/851) ## 2025-05-19 - Go SDK 0.18.0-alpha.2 diff --git a/runtime/db/db.go b/runtime/db/db.go index 205c9f826..d8ace49c3 100644 --- a/runtime/db/db.go +++ b/runtime/db/db.go @@ -51,6 +51,10 @@ func Stop(ctx context.Context) { close(globalRuntimePostgresWriter.quit) <-globalRuntimePostgresWriter.done pool.Close() + + if _embeddedPostgresDB != nil { + shutdownEmbeddedPostgresDB(ctx) + } } func logDbWarningOrError(ctx context.Context, err error, msg string) { @@ -393,9 +397,20 @@ func QueryCollectionVectorsFromCheckpoint(ctx context.Context, collectionName, s } func Initialize(ctx context.Context) { + if useModusDB() { + return + } + + if useEmbeddedPostgres() { + if err := prepareEmbeddedPostgresDB(ctx); err != nil { + logger.Fatal(ctx).Err(err).Msg("Failed to prepare embedded Postgres database.") + return + } + } + // this will initialize the pool and start the worker _, err := globalRuntimePostgresWriter.GetPool(ctx) - if err != nil && !useModusDB() { + if err != nil { logger.Warn(ctx).Err(err).Msg("Metadata database is not available.") } go globalRuntimePostgresWriter.worker(ctx) @@ -437,7 +452,6 @@ var _useModusDB bool func useModusDB() bool { _useModusDBOnce.Do(func() { - // this gives us a way to force the use or disuse of ModusDB for development s := os.Getenv("MODUS_DB_USE_MODUSDB") if s != "" { if value, err := strconv.ParseBool(s); err == nil { @@ -446,8 +460,11 @@ func useModusDB() bool { } } - // otherwise, it's based on the environment - _useModusDB = app.IsDevEnvironment() + if app.IsDevEnvironment() { + _useModusDB = !useEmbeddedPostgres() + } else { + _useModusDB = false + } }) return _useModusDB } diff --git a/runtime/db/embeddedpg.go b/runtime/db/embeddedpg.go new file mode 100644 index 000000000..3b5435c79 --- /dev/null +++ b/runtime/db/embeddedpg.go @@ -0,0 +1,226 @@ +/* + * Copyright 2025 Hypermode Inc. + * Licensed under the terms of the Apache License, Version 2.0 + * See the LICENSE file that accompanied this code for further details. + * + * SPDX-FileCopyrightText: 2025 Hypermode Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +package db + +import ( + "bufio" + "context" + "embed" + "fmt" + "net" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + + "github.com/fatih/color" + "github.com/hypermodeinc/modus/runtime/app" + "github.com/hypermodeinc/modus/runtime/logger" + "github.com/rs/zerolog" + + embeddedpostgres "github.com/fergusstrange/embedded-postgres" + "github.com/golang-migrate/migrate/v4" + _ "github.com/golang-migrate/migrate/v4/database/postgres" + "github.com/golang-migrate/migrate/v4/source/iofs" + _ "github.com/golang-migrate/migrate/v4/source/iofs" +) + +//go:embed migrations/*.sql +var migrationsFS embed.FS + +func useEmbeddedPostgres() bool { + s := os.Getenv("MODUS_DB_USE_EMBEDDED_POSTGRES") + if s != "" { + if value, err := strconv.ParseBool(s); err == nil { + return value + } + } + return runtime.GOOS == "windows" +} + +var _embeddedPostgresDB *embeddedpostgres.EmbeddedPostgres + +func getEmbeddedPostgresDataDir(ctx context.Context) string { + var dataDir string + appPath := app.Config().AppPath() + if filepath.Base(appPath) == "build" { + // this keeps the data directory outside of the build directory + dataDir = filepath.Join(appPath, "..", ".postgres") + addToGitIgnore(ctx, filepath.Dir(appPath), ".postgres/") + } else { + dataDir = filepath.Join(appPath, ".postgres") + } + return dataDir +} + +func prepareEmbeddedPostgresDB(ctx context.Context) error { + + dataDir := getEmbeddedPostgresDataDir(ctx) + + if err := shutdownPreviousEmbeddedPostgresDB(ctx, dataDir); err != nil { + return fmt.Errorf("error shutting down previous embedded postgres instance: %w", err) + } + + port, err := findAvailablePort(5432, 5499) + if err != nil { + return err + } + + logger.Info(ctx).Msg("Preparing embedded PostgreSQL database. The db instance will log its output next:") + + // Note: releases come from here: + // https://github.com/zonkyio/embedded-postgres-binaries/releases + + dbname := "modusdb" + cfg := embeddedpostgres.DefaultConfig(). + Port(port). + Database(dbname). + DataPath(dataDir). + Version("17.4.0"). + OwnProcessGroup(true). + BinariesPath(getEmbeddedPostgresBinariesPath()) + + db := embeddedpostgres.NewDatabase(cfg) + if err := db.Start(); err != nil { + return fmt.Errorf("failed to start embedded postgres: %w", err) + } + + cs := fmt.Sprintf("postgres://postgres:postgres@localhost:%d/%s?sslmode=disable", port, dbname) + + d, err := iofs.New(migrationsFS, "migrations") + if err != nil { + return fmt.Errorf("error creating iofs source: %w", err) + } + + m, err := migrate.NewWithSourceInstance("iofs", d, cs) + if err != nil { + return fmt.Errorf("error creating db migrate instance: %w", err) + } + m.Log = &migrateLogger{ + logger: logger.Get(ctx), + } + + if err := m.Up(); err != nil && err != migrate.ErrNoChange { + return fmt.Errorf("error running db migrations: %w", err) + } + + _embeddedPostgresDB = db + os.Setenv("MODUS_DB", cs) + + logger.Info(ctx).Msg("Embedded PostgreSQL database started successfully.") + return nil +} + +func getEmbeddedPostgresBinariesPath() string { + return filepath.Join(app.ModusHomeDir(), "postgres") +} + +func findAvailablePort(startPort, maxPort uint32) (uint32, error) { + for port := startPort; port <= maxPort; port++ { + addr := fmt.Sprintf("localhost:%d", port) + listener, err := net.Listen("tcp", addr) + if err == nil { + listener.Close() + return port, nil + } + } + return 0, fmt.Errorf("no available db ports between %d and %d", startPort, maxPort) +} + +func shutdownEmbeddedPostgresDB(ctx context.Context) { + logger.Info(ctx).Msg("Shutting down embedded PostgreSQL database server:") + + if err := _embeddedPostgresDB.Stop(); err != nil { + logger.Error(ctx).Err(err).Msg("Failed to stop embedded PostgreSQL database.") + } +} + +func shutdownPreviousEmbeddedPostgresDB(ctx context.Context, dataDir string) error { + + // does dataDir exist? + if _, err := os.Stat(dataDir); err != nil { + if os.IsNotExist(err) { + return nil + } + return fmt.Errorf("error checking dataDir: %w", err) + } + + // does `postmaster.pid` exist? + pidFile := filepath.Join(dataDir, "postmaster.pid") + if _, err := os.Stat(pidFile); err != nil { + if os.IsNotExist(err) { + return nil + } + } + + logger.Warn(ctx).Msg("Previous embedded PostgreSQL instance was not shut down cleanly. Shutting it down now:") + + // first try to shutdown the process cleanly + pgctl := filepath.Join(getEmbeddedPostgresBinariesPath(), "bin", "pg_ctl") + if runtime.GOOS == "windows" { + pgctl += ".exe" + } + if _, err := os.Stat(pgctl); err == nil { + p := exec.Command(pgctl, "stop", "-w", "-D", dataDir) + p.Stdout = os.Stdout + p.Stderr = os.Stderr + if err := p.Run(); err == nil { + return nil + } else { + logger.Err(ctx, err).Msg("Failed to stop embedded PostgreSQL instance cleanly. Killing db process.") + } + } + + // read the pid from the first line of the file + file, err := os.Open(pidFile) + if err != nil { + return fmt.Errorf("error opening pid file: %w", err) + } + defer file.Close() + scanner := bufio.NewScanner(file) + if scanner.Scan() { + pidStr := scanner.Text() + pid, err := strconv.Atoi(pidStr) + if err != nil { + return fmt.Errorf("error parsing pid: %w", err) + } + + // kill the process + process, err := os.FindProcess(pid) + if err != nil { + return fmt.Errorf("error finding process: %w", err) + } + if err := process.Kill(); err != nil { + return fmt.Errorf("error killing process: %w", err) + } + } + + return nil +} + +var migrateLoggerColor = color.New(color.FgWhite, color.Faint) + +type migrateLogger struct { + logger *zerolog.Logger + started bool +} + +func (l *migrateLogger) Printf(format string, v ...interface{}) { + if !l.started { + l.logger.Info().Msg("Applying db migrations:") + l.started = true + } + migrateLoggerColor.Fprintf(os.Stderr, " "+format, v...) +} + +func (l *migrateLogger) Verbose() bool { + return false +} diff --git a/runtime/db/modusdb.go b/runtime/db/modusdb.go index 4e22a4cf2..d608efa25 100644 --- a/runtime/db/modusdb.go +++ b/runtime/db/modusdb.go @@ -15,7 +15,6 @@ import ( "errors" "os" "path/filepath" - "runtime" "github.com/hypermodeinc/modus/runtime/app" "github.com/hypermodeinc/modus/runtime/logger" @@ -26,9 +25,7 @@ import ( var GlobalModusDbEngine *modusgraph.Engine func InitModusDb(ctx context.Context) { - if !useModusDB() || runtime.GOOS == "windows" { - // ModusDB should only be initialized in dev environment, - // and currently does not work on Windows. + if !useModusDB() { return } @@ -37,7 +34,7 @@ func InitModusDb(ctx context.Context) { if filepath.Base(appPath) == "build" { // this keeps the data directory outside of the build directory dataDir = filepath.Join(appPath, "..", ".modusdb") - addToGitIgnore(ctx, filepath.Dir(appPath)) + addToGitIgnore(ctx, filepath.Dir(appPath), ".modusdb/") } else { dataDir = filepath.Join(appPath, ".modusdb") } @@ -55,19 +52,18 @@ func CloseModusDb(ctx context.Context) { } } -func addToGitIgnore(ctx context.Context, rootPath string) { +func addToGitIgnore(ctx context.Context, rootPath, contents string) { gitIgnorePath := filepath.Join(rootPath, ".gitignore") - gitIgnoreContents := ".modusdb/" - // if .gitignore file does not exist, create it and add .modusdb/ to it + // if .gitignore file does not exist, create it and add contents to it if _, err := os.Stat(gitIgnorePath); errors.Is(err, os.ErrNotExist) { - if err := os.WriteFile(gitIgnorePath, []byte(gitIgnoreContents+"\n"), 0644); err != nil { + if err := os.WriteFile(gitIgnorePath, []byte(contents+"\n"), 0644); err != nil { logger.Err(ctx, err).Msg("Failed to create .gitignore file.") } return } - // check if .modusdb/ is already in the .gitignore file + // check if contents are already in the .gitignore file file, err := os.Open(gitIgnorePath) if err != nil { logger.Err(ctx, err).Msg("Failed to open .gitignore file.") @@ -76,20 +72,19 @@ func addToGitIgnore(ctx context.Context, rootPath string) { defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { - if scanner.Text() == gitIgnoreContents { - // found .modusdb/ in the file - return + if scanner.Text() == contents { + return // found } } - // .modusdb/ is not in the file, so append it + // contents are not in the file, so append them file, err = os.OpenFile(gitIgnorePath, os.O_APPEND|os.O_WRONLY, 0644) if err != nil { logger.Err(ctx, err).Msg("Failed to open .gitignore file.") return } defer file.Close() - if _, err := file.WriteString("\n" + gitIgnoreContents + "\n"); err != nil { - logger.Err(ctx, err).Msg("Failed to append .modusdb/ to .gitignore file.") + if _, err := file.WriteString("\n" + contents + "\n"); err != nil { + logger.Err(ctx, err).Msg("Failed to append " + contents + " to .gitignore file.") } } diff --git a/runtime/explorer/explorer.go b/runtime/explorer/explorer.go index 3aff84760..835a8d618 100644 --- a/runtime/explorer/explorer.go +++ b/runtime/explorer/explorer.go @@ -13,7 +13,6 @@ import ( "embed" "io/fs" "net/http" - "runtime" "github.com/hypermodeinc/modus/lib/manifest" "github.com/hypermodeinc/modus/runtime/db" @@ -32,14 +31,7 @@ func explorerHandler(w http.ResponseWriter, r *http.Request) { mux := http.NewServeMux() mux.Handle("/explorer/", http.StripPrefix("/explorer/", http.FileServerFS(contentRoot))) mux.HandleFunc("/explorer/api/endpoints", endpointsHandler) - if runtime.GOOS == "windows" { - notImplementedHandler := func(w http.ResponseWriter, r *http.Request) { - http.Error(w, "Not implemented on Windows", http.StatusNotImplemented) - } - mux.HandleFunc("/explorer/api/inferences", notImplementedHandler) - } else { - mux.HandleFunc("/explorer/api/inferences", inferenceHistoryHandler) - } + mux.HandleFunc("/explorer/api/inferences", inferenceHistoryHandler) mux.ServeHTTP(w, r) } diff --git a/runtime/go.mod b/runtime/go.mod index 118492eb7..aa952b192 100644 --- a/runtime/go.mod +++ b/runtime/go.mod @@ -16,12 +16,14 @@ require ( github.com/docker/docker v28.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/fatih/color v1.18.0 + github.com/fergusstrange/embedded-postgres v1.30.0 github.com/getsentry/sentry-go v0.33.0 github.com/go-sql-driver/mysql v1.9.2 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/goccy/go-json v0.10.5 github.com/gofrs/flock v0.12.1 github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/golang-migrate/migrate/v4 v4.18.3 github.com/google/renameio/v2 v2.0.0 github.com/google/uuid v1.6.0 github.com/hypermodeinc/modus/lib/manifest v0.17.2 @@ -176,6 +178,7 @@ require ( github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc/v3 v3.0.0-beta2 // indirect github.com/lestrrat-go/option v1.0.1 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/miekg/dns v1.1.65 // indirect @@ -236,6 +239,7 @@ require ( github.com/wundergraph/cosmo/router v0.0.0-20240729154441-b20b00e892c6 // indirect github.com/xdg/scram v1.0.5 // indirect github.com/xdg/stringprep v1.0.3 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect go.akshayshah.org/connectproto v0.6.0 // indirect go.etcd.io/etcd/raft/v3 v3.5.21 // indirect @@ -265,3 +269,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect rogchap.com/v8go v0.9.0 // indirect ) + +// temporary +replace github.com/fergusstrange/embedded-postgres => github.com/mattjohnsonpint/embedded-postgres v0.0.0-20250520224003-29c7555eee5e diff --git a/runtime/go.sum b/runtime/go.sum index 2217ea34b..073434891 100644 --- a/runtime/go.sum +++ b/runtime/go.sum @@ -219,6 +219,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/dhui/dktest v0.4.5 h1:uUfYBIVREmj/Rw6MvgmqNAYzTiKOHJak+enB5Di73MM= +github.com/dhui/dktest v0.4.5/go.mod h1:tmcyeHDKagvlDrz7gDKq4UAJOLIfVZYkfD5OnHDwcCo= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= @@ -321,6 +323,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs= +github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I= github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U= @@ -565,12 +569,16 @@ github.com/lestrrat-go/jwx/v3 v3.0.1 h1:fH3T748FCMbXoF9UXXNS9i0q6PpYyJZK/rKSbkt2 github.com/lestrrat-go/jwx/v3 v3.0.1/go.mod h1:XP2WqxMOSzHSyf3pfibCcfsLqbomxakAnNqiuaH8nwo= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora/v3 v3.0.0 h1:R6zcoZZbvVcGMvDCKo45A9U/lzYyzl5NfYIvznmDfE4= github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattjohnsonpint/embedded-postgres v0.0.0-20250520224003-29c7555eee5e h1:UpfOdtNjN2tkWtpAJGtEO1rPqtNkDPXzsLmHroB+VuQ= +github.com/mattjohnsonpint/embedded-postgres v0.0.0-20250520224003-29c7555eee5e/go.mod h1:w0YvnCgf19o6tskInrOOACtnqfVlOvluz3hlNLY7tRk= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -855,6 +863,8 @@ github.com/xdg/scram v1.0.5 h1:TuS0RFmt5Is5qm9Tm2SoD89OPqe4IRiFtyFY4iwWXsw= github.com/xdg/scram v1.0.5/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.3 h1:cmL5Enob4W83ti/ZHuZLuKD/xqJfus4fVPwE+/BDm+4= github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xo/dburl v0.23.7 h1:UCiK8Dyll38NdDHVi7UOxhz5/ugWuyQGgQHdxfdEQDY= github.com/xo/dburl v0.23.7/go.mod h1:uazlaAQxj4gkshhfuuYyvwCBouOmNnG2aDxTCFZpmL4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -888,8 +898,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSG go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 h1:o8iWeVFa1BcLtVEV0LzrCxV2/55tB3xLxADr6Kyoey4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1/go.mod h1:SEVfdK4IoBnbT2FXNM/k8yC08MrfbhWk3U4ljM8B3HE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= @@ -900,8 +910,8 @@ go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= diff --git a/runtime/services/services.go b/runtime/services/services.go index 40cacf636..41545a03b 100644 --- a/runtime/services/services.go +++ b/runtime/services/services.go @@ -86,4 +86,6 @@ func Stop(ctx context.Context) { logger.Close() db.Stop(ctx) db.CloseModusDb(ctx) + + logger.Info(ctx).Msg("Shutdown complete.") } diff --git a/sdk/assemblyscript/examples/agents/.gitignore b/sdk/assemblyscript/examples/agents/.gitignore index 73064806d..caeb06765 100644 --- a/sdk/assemblyscript/examples/agents/.gitignore +++ b/sdk/assemblyscript/examples/agents/.gitignore @@ -15,3 +15,4 @@ node_modules/ logs/ .modusdb/ +.postgres/ diff --git a/sdk/go/examples/agents/.gitignore b/sdk/go/examples/agents/.gitignore index 2b5c5ded9..7ad56473e 100644 --- a/sdk/go/examples/agents/.gitignore +++ b/sdk/go/examples/agents/.gitignore @@ -1 +1,2 @@ .modusdb/ +.postgres/