mirror of
https://github.com/hanzoai/base.git
synced 2026-10-21 03:41:50 +00:00
An extension's hooks were stated once, on the Base the process started with, so a write to a tenant's Base fired nothing an extension had asked for. The file says what to do when a record is created; it does not say where, and the where comes with the event. So a declaration is recorded as something that can be stated on any Base, and stated on each as it is constructed — the same place realtime is bound, for the same reason. A hook still sees only the Base it fired on. This grants an extension nothing it did not have. A file on disk is the operator's, and it already ran with the process's authority; what changes is which data its hooks see. An extension written when there was one Base now runs against each, which is a behaviour change and is the thing to know. Routes and crons an extension declares stay on the Base that loaded it: a route is registered once on a router, and a schedule belongs to the process. A tenant's Base was bootstrapped and never served, so nothing it scheduled ever ran — its logs were never cleaned and its database never optimised. Co-authored-by: Hanzo Dev <[email protected]>
63 lines
2.1 KiB
Go
63 lines
2.1 KiB
Go
package org
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/hanzoai/base/tests"
|
|
)
|
|
|
|
// A Base looks after itself. The periodic checkpoint and the log cleanup are
|
|
// registered where a Base is constructed and where its logger is built, and a
|
|
// schedule starts ticking when it is added — so an org's Base keeps its own
|
|
// write-ahead log checkpointed and its own logs inside its own retention,
|
|
// without anything serving on it.
|
|
//
|
|
// The alternative reading is easy to arrive at and wrong: __hzCronStart__ is
|
|
// bound on OnServe, and a tenant's Base is bootstrapped and never served, so it
|
|
// looks as though its schedules never start. Start resumes what Stop paused;
|
|
// nothing here is ever paused. The two schedules below are what would silently
|
|
// stop if that ever became true, and neither failure announces itself — a Base
|
|
// that is not checkpointed grows a write-ahead log, and one whose logs are not
|
|
// cleaned keeps them past the days its settings allow.
|
|
//
|
|
// The autobackup schedule is the third of the set and is absent until a Base's
|
|
// settings name a cron for it, which is the same on every Base.
|
|
func TestATenantsBaseMaintainsItself(t *testing.T) {
|
|
app, err := tests.NewTestApp()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer app.Cleanup()
|
|
|
|
b := newBases(&plugin{app: app, orgDB: NewOrgDB(app, "")})
|
|
|
|
tenant, err := b.base("acme")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
for _, id := range []string{"__hzDBOptimize__", "__hzLogsCleanup__"} {
|
|
if !tenant.Cron().HasJob(id) {
|
|
t.Fatalf("an org's Base does not run %s, so nothing maintains it", id)
|
|
}
|
|
}
|
|
|
|
if tenant.Cron().HasJob("__hzAutoBackup__") {
|
|
t.Fatal("an org's Base scheduled a backup its settings did not ask for")
|
|
}
|
|
|
|
// Registered is not running. This is the half that the OnServe reading
|
|
// would take away.
|
|
if !tenant.Cron().HasStarted() {
|
|
t.Fatal("an org's Base registered its maintenance and never started it")
|
|
}
|
|
|
|
// And they belong to the Base: closing it stops them, so a process that
|
|
// opens many orgs is not left ticking for the ones it has released.
|
|
b.close()
|
|
|
|
if tenant.Cron().HasStarted() {
|
|
t.Fatal("an org's Base kept ticking after it was closed")
|
|
}
|
|
}
|