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.

gox
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:

gox
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:

gox
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.

gox
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:

  • OnStartServer does not run when recharge.
  • The OnStopServer previous does not run when recharge.
  • When the instance is closed, the OnStopServer of the active configuration.
  • The existing values of gox.Storage remain 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.

See also

Next step

Continue with CLI to know the commands available to create, run and manage a GOX project.

CLI