Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions site/pro-reference-baseline.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"module": "echo.labstack.com/pro",
"version": "v0.1.0",
"version": "v0.2.0",
"configs": {
"admin.Config": [
{
Expand Down Expand Up @@ -1113,7 +1113,7 @@
},
{
"name": "Mode",
"type": "ExecutionMode",
"type": "Mode",
"doc": "Mode empty selects ExternalMode; TransactionalMode is explicit.",
"default": "Mode empty selects ExternalMode; TransactionalMode is explicit."
}
Expand Down Expand Up @@ -2783,7 +2783,7 @@
"quota.MiddlewareConfig.ToMiddleware": "func (cfg MiddlewareConfig) ToMiddleware() (echo.MiddlewareFunc, error)",
"quota.New": "func New(cfg Config) (*Limiter, error)",
"quota.NewMemoryStore": "func NewMemoryStore(cfg MemoryConfig) *MemoryStore",
"quota.NewTopK": "func NewTopK(k int) *TopK",
"quota.NewTopK": "func NewTopK(k int) (*TopK, error)",
"quotaadmin.New": "func New(cfg Config) (*Panel, error)",
"quotaadmin.NewDenialRecorder": "func NewDenialRecorder(size int) (*DenialRecorder, error)",
"quotamcp.MiddlewareConfig.ToMiddleware": "func (c MiddlewareConfig) ToMiddleware() (mcp.Middleware, error)",
Expand Down
64 changes: 32 additions & 32 deletions site/pro-source/config-fields.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"module": "echo.labstack.com/pro",
"revision": "v0.1.0",
"revision": "v0.2.0",
"configs": [
{
"name": "admin.Config",
Expand Down Expand Up @@ -669,7 +669,7 @@
"name": "auth.APIKey",
"file": "auth/apikey.go",
"line": 205,
"doc": "APIKey configures a key-store scheme. Header sets an optional alternative to\nAuthorization: ApiKey. Supplying credentials in both headers is rejected.\nLookupTimeout defaults to 2s (1ms–30s). The store stays caller-owned and must honor\ncancellation. No goroutines start. Construction copies the pepper ring and key bytes.\nCancellation and lookup failures return a sanitized *Failure without exposing store or\ncontext errors.",
"doc": "APIKey configures a key-store scheme. Header sets an optional alternative to\nAuthorization: ApiKey. Supplying credentials in both headers is rejected.\nLookupTimeout defaults to 2s (1ms–30s). The store stays caller-owned and must honor\ncancellation. No goroutines start. Construction copies the pepper ring and key bytes.\nCancellation and lookup failures return a sanitized *FailureError without exposing store or\ncontext errors.",
"fields": [
{
"name": "Namespace",
Expand Down Expand Up @@ -1230,43 +1230,43 @@
{
"name": "execution.Limits",
"file": "execution/types.go",
"line": 87,
"line": 88,
"doc": "Limits are immutable per namespace; zero values select documented defaults.",
"fields": [
{
"name": "MaxResultBytes",
"type": "int",
"doc": "MaxResultBytes defaults to 64 KiB; valid range 1 byte–1 MiB.",
"default": "MaxResultBytes defaults to 64 KiB; valid range 1 byte–1 MiB.",
"line": 87
"line": 88
},
{
"name": "MaxUnresolvedPerTenant",
"type": "int",
"doc": "MaxUnresolvedPerTenant defaults to 1000 and must be positive.",
"default": "MaxUnresolvedPerTenant defaults to 1000 and must be positive.",
"line": 87
"line": 88
},
{
"name": "MaxNamespaceRecords",
"type": "int64",
"doc": "MaxNamespaceRecords defaults to 5000000 and must be positive.",
"default": "MaxNamespaceRecords defaults to 5000000 and must be positive.",
"line": 87
"line": 88
},
{
"name": "MaxNamespaceBytes",
"type": "int64",
"doc": "MaxNamespaceBytes defaults to 20 GiB of logical charges and must be positive.",
"default": "MaxNamespaceBytes defaults to 20 GiB of logical charges and must be positive.",
"line": 87
"line": 88
},
{
"name": "BudgetShards",
"type": "int",
"doc": "BudgetShards defaults to 16; valid range 1–256.",
"default": "BudgetShards defaults to 16; valid range 1–256.",
"line": 87
"line": 88
}
]
},
Expand Down Expand Up @@ -1372,71 +1372,71 @@
{
"name": "execution.Policy",
"file": "execution/types.go",
"line": 77,
"line": 78,
"doc": "Policy declares effects and their safety rules. New owns copied slices. Zero tunables\nselect Lease=1 minute, ResultRetention=24 hours, KeyRetention=7 days. Effects require\nexplicit timeouts. Backend selection comes only from the injected Store; a policy\ncarries no storage selector. An empty fingerprint selects http/v1; nil Headers selects\nIf-Match, If-None-Match, If-Modified-Since, If-Unmodified-Since, Content-Encoding and\nContent-Language, while an explicit empty slice selects none. An empty Mode selects\nExternalMode; TransactionalMode requires no effects, a zero Lease and an empty\nReconcilerVersion.",
"fields": [
{
"name": "SafetyVersion",
"type": "string",
"doc": "SafetyVersion is required and versions the operation's safety rules.",
"default": "SafetyVersion is required and versions the operation's safety rules.",
"line": 77
"line": 78
},
{
"name": "Scope",
"type": "string",
"doc": "Scope empty defaults to the configured operation name in Journal.New.",
"default": "Scope empty defaults to the configured operation name in Journal.New.",
"line": 77
"line": 78
},
{
"name": "ReconcilerVersion",
"type": "string",
"doc": "ReconcilerVersion is required for external mode and empty for transactional mode.",
"default": "ReconcilerVersion is required for external mode and empty for transactional mode.",
"line": 77
"line": 78
},
{
"name": "Effects",
"type": "[]Effect",
"doc": "Effects requires 1–8 entries in external mode; transactional mode requires none.",
"default": "Effects requires 1–8 entries in external mode; transactional mode requires none.",
"line": 77
"line": 78
},
{
"name": "Fingerprint",
"type": "FingerprintSpec",
"doc": "Fingerprint at zero selects http/v1 with its default header set.",
"default": "Fingerprint at zero selects http/v1 with its default header set.",
"line": 77
"line": 78
},
{
"name": "Lease",
"type": "time.Duration",
"doc": "Lease defaults to 1m in external mode; transactional mode requires zero.",
"default": "Lease defaults to 1m in external mode; transactional mode requires zero.",
"line": 77
"line": 78
},
{
"name": "ResultRetention",
"type": "time.Duration",
"doc": "ResultRetention defaults to 24h and must be positive.",
"default": "ResultRetention defaults to 24h and must be positive.",
"line": 77
"line": 78
},
{
"name": "KeyRetention",
"type": "time.Duration",
"doc": "KeyRetention defaults to 7 days and must be at least ResultRetention.",
"default": "KeyRetention defaults to 7 days and must be at least ResultRetention.",
"line": 77
"line": 78
},
{
"name": "Mode",
"type": "ExecutionMode",
"type": "Mode",
"doc": "Mode empty selects ExternalMode; TransactionalMode is explicit.",
"default": "Mode empty selects ExternalMode; TransactionalMode is explicit.",
"line": 77
"line": 78
}
]
},
Expand Down Expand Up @@ -2787,71 +2787,71 @@
{
"name": "stripeadmin.Config",
"file": "quota/quotastripe/stripeadmin/panel.go",
"line": 37,
"line": 36,
"doc": "Config selects the caller-owned status reader. Status and optional readers\nare retained for the panel lifetime, never closed; all must be concurrency\nsafe and honor cancellation.",
"fields": [
{
"name": "Status",
"type": "StatusReader",
"doc": "Status is required, retained and caller-owned; it must honor ctx and\nbe concurrency safe.",
"default": "Status is required, retained and caller-owned; it must honor ctx and be concurrency safe.",
"line": 40
"line": 39
},
{
"name": "Inspection",
"type": "InspectionReader",
"doc": "Inspection enables bounded shared-store diagnostic views. Nil omits them.",
"default": "Nil omits them.",
"line": 42
"line": 41
},
{
"name": "Reconcile",
"type": "ReconcileReader",
"doc": "Reconcile enables a probe that compares exported totals with Stripe usage. Nil omits\nthe action.",
"default": "Nil omits the action.",
"line": 45
"line": 44
},
{
"name": "Flush",
"type": "FlushRunner",
"doc": "Flush enables an action that seals and dispatches eligible usage through the local\ndispatcher. The request is saved durably for retries. Nil omits the action.",
"default": "Nil omits the action.",
"line": 48
"line": 47
},
{
"name": "Budget",
"type": "quotastripe.InspectionBudget",
"doc": "Budget bounds inspection; zero uses quotastripe defaults.",
"default": "Budget bounds inspection; zero uses quotastripe defaults.",
"line": 50
"line": 49
},
{
"name": "StripePages",
"type": "int",
"doc": "StripePages defaults to 10 and must be 1–100. Shared across Probe retries.",
"default": "StripePages defaults to 10 and must be 1–100.",
"line": 52
"line": 51
},
{
"name": "ID",
"type": "string",
"doc": "ID defaults to stripe; use 1–32 lowercase ASCII letters, digits or\nhyphens, starting with a letter, excluding api and assets.",
"default": "ID defaults to stripe; use 1–32 lowercase ASCII letters, digits or hyphens, starting with a letter, excluding api and assets.",
"line": 55
"line": 54
},
{
"name": "BacklogAlarm",
"type": "time.Duration",
"doc": "BacklogAlarm is a display threshold; defaults to 30m, nonzero values\nmust be positive.",
"default": "BacklogAlarm is a display threshold; defaults to 30m, nonzero values must be positive.",
"line": 58
"line": 57
},
{
"name": "Now",
"type": "func() time.Time",
"doc": "Now is retained and must be concurrency safe; nil uses time.Now.",
"default": "Now is retained and must be concurrency safe; nil uses time.Now.",
"line": 60
"line": 59
}
]
},
Expand Down Expand Up @@ -3722,9 +3722,9 @@
},
{
"name": "quota.NewTopK",
"signature": "func NewTopK(k int) *TopK",
"signature": "func NewTopK(k int) (*TopK, error)",
"file": "quota/topk.go",
"line": 62
"line": 63
},
{
"name": "quotaadmin.New",
Expand Down Expand Up @@ -3808,7 +3808,7 @@
"name": "stripeadmin.New",
"signature": "func New(cfg Config) (*Panel, error)",
"file": "quota/quotastripe/stripeadmin/panel.go",
"line": 68
"line": 67
},
{
"name": "tenant.AuthorizeConfig.ToMiddleware",
Expand Down
25 changes: 16 additions & 9 deletions site/pro-source/examples/admin-demo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ import (
)

func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

func run() error {
// Do not put the URL in flag defaults: -help must never disclose credentials.
var databaseURL string
flag.StringVar(
Expand All @@ -46,13 +53,13 @@ func main() {
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
if err := run(ctx, databaseURL, *addr); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
if err := runWithContext(ctx, databaseURL, *addr); err != nil {
return err
}
return nil
}

func run(ctx context.Context, databaseURL, addr string) error {
func runWithContext(ctx context.Context, databaseURL, addr string) error {
if databaseURL == "" {
return errors.New(
"provide -postgres-url or ADMIN_DEMO_POSTGRES_URL; use the " +
Expand Down Expand Up @@ -121,7 +128,7 @@ func run(ctx context.Context, databaseURL, addr string) error {
Maintenance: prefix + "_maintenance",
Reader: prefix + "_reader",
}
if err = createRoles(ctx, pool, roles); err != nil {
if err := createRoles(ctx, pool, roles); err != nil {
return err
}
}
Expand Down Expand Up @@ -247,20 +254,20 @@ func run(ctx context.Context, databaseURL, addr string) error {
Origins: []string{"http://" + demoBrowserAuthority(authority)},
}
//nolint:contextcheck // Mount registers routes; request contexts originate in Echo.
if err = cfg.Mount(e, "/admin"); err != nil {
if err := cfg.Mount(e, "/admin"); err != nil {
return err
}
// executionadmin binds one namespace. A second console exposes the other.
cfg.Panels = []admin.Panel{qp, sp, op, fp, wp, ap}
//nolint:contextcheck // Mount registers routes; request contexts originate in Echo.
if err = cfg.Mount(e, "/admin-fulfillment"); err != nil {
if err := cfg.Mount(e, "/admin-fulfillment"); err != nil {
return err
}
if err = mountSamples(ctx, e, lim, op, append(records, fulfillment...)); err != nil {
if err := mountSamples(ctx, e, lim, op, append(records, fulfillment...)); err != nil {
return err
}
for _, mount := range []string{"/admin", "/admin-fulfillment"} {
if err = admin.VerifyRoutes(e, mount); err != nil {
if err := admin.VerifyRoutes(e, mount); err != nil {
return err
}
}
Expand Down
5 changes: 4 additions & 1 deletion site/pro-source/examples/admin-demo/quota.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ func seedQuota(ctx context.Context) (*quota.Limiter, *quotaadmin.Panel, error) {
if err != nil {
return nil, nil, err
}
top := quota.NewTopK(10)
top, err := quota.NewTopK(10)
if err != nil {
return nil, nil, err
}
//nolint:contextcheck // Construction has no context API; no Outbox is configured.
lim, err := quota.New(quota.Config{Store: quota.NewMemoryStore(quota.MemoryConfig{}), Hooks: quota.JoinHooks(top.Hooks(), denials.Hooks()), Plans: []quota.Plan{
{ID: "team", Limits: []quota.Limit{quota.PerDay("daily", 100).Meter("requests"), quota.Credits("credits").Meter("tokens")}},
Expand Down
2 changes: 1 addition & 1 deletion site/pro-source/examples/admin-demo/reports.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func seedStripe(ctx context.Context) (*stripeadmin.Panel, error) {
}
for i := range 24 {
event := quota.ConsumptionEvent{ID: fmt.Sprintf("offline-usage-%03d", i), Identity: quota.Identity{Tenant: demoTenants[i%4]}, Plan: "team", Meter: "tokens", Amount: int64(80 + i*19), At: time.Now().UTC().Add(-time.Duration(i*11+1) * time.Minute).Truncate(time.Millisecond)}
if err = exporter.Deliver(ctx, quota.Event{ID: event.ID, Consumption: &event}); err != nil {
if err := exporter.Deliver(ctx, quota.Event{ID: event.ID, Consumption: &event}); err != nil {
return nil, err
}
}
Expand Down
2 changes: 1 addition & 1 deletion site/pro-source/examples/admin-demo/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func seedWebhooks(ctx context.Context, pool *pgxpool.Pool, schema string) (resul
if admitErr != nil {
return nil, admitErr
}
if err = webhookSnapshot(ctx, pool, schema, receipt.Ref, direction, state); err != nil {
if err := webhookSnapshot(ctx, pool, schema, receipt.Ref, direction, state); err != nil {
return nil, err
}
}
Expand Down
Loading
Loading