Lifecycle
OnStartServer and OnStopServer allow to open and close resources shared throughout the application. A common case is to open the connection to a database during the start, save it in gox.Storage and reuse it from Pages, Actions and WebSocket.
Both hooks belong to the root structure described in Configuration.
OnStartServer: startup.OnStartServer,
OnStopServer: shutdown.OnStopServer, Both fields are optional and accept a function with the signature func() error.
OnStartServer
OnStartServer is executed once during the start of the instance, after preparing the internal remedies of the runtime and before accepting requests.
The following example opens MongolDB and keeps the client in the global storage:
module startup
import (
"context"
"time"
"github.com/gox-lang/gox"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func OnStartServer() error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
return err
}
if err := client.Ping(ctx, nil); err != nil {
client.Disconnect(context.Background())
return err
}
gox.Storage.Set("mongo", client)
return nil
} If you return an error, GOX cancels the start and releases the domestic remedies that it had already opened.
Reuse the resource
A Page or Action can recover the same client by its specific type:
var client *mongo.Client
exists, err := gox.Storage.Get("mongo", &client)
if err != nil || !exists {
return ctx.Response.DoneWith(500)
}
users := client.Database("app").Collection("users") The same pattern can be used within a WebSocket handler. gox.Storage is shared by the process and is safe for concurrent access. Pages, Actions and WebSocket to know each point of consumption.
OnStopServer
OnStopServer it runs once during the closure of the instance. It must release the resources opened by the application.
module shutdown
import (
"context"
"time"
"github.com/gox-lang/gox"
"go.mongodb.org/mongo-driver/mongo"
)
func OnStopServer() error {
var client *mongo.Client
exists, err := gox.Storage.Get("mongo", &client)
if err != nil || !exists {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
gox.Storage.Delete("mongo")
return client.Disconnect(ctx)
} If you return an error, GOX records it and continues to close sessions, cluster and other domestic remedies.
Hot reload
Hot relay replaces the configured references, but does not represent a new start or closure of the instance. Therefore:
OnStartServerdoes not run when recharge.- The
OnStopServerprevious does not run when recharge. - When the instance is closed, the
OnStopServerof the active configuration. - The existing values of
gox.Storageremain in memory.
To run the initialization again, close the instance and run again gox run.
Best practices
- Returns any connection error to prevent an incomplete start.
- Check the connection before saving it.
- Use stable keys and specific types when reading
gox.Storage. - Apply timeouts to the connection and closure of external resources.
- It removes from the storage the resources you have already closed.
- Make the closure idempotent.
- Don't assume that the hooks run during hot relax.