feat: release v0.27 unified HTTP limits and safe request shutdown

This commit is contained in:
2026-09-29 23:24:19 +08:00
parent 859f1851b1
commit 3b00bb55d1
42 changed files with 1191 additions and 70 deletions

View File

@@ -68,6 +68,10 @@ func (r *Runtime) OnClose(cleanup func() error) {
// skips resource callbacks and returns ErrResourcesRetained. Once release is
// safe, all OnClose callbacks are attempted even if one fails or panics.
func (r *Runtime) Close() error {
return r.close(false)
}
func (r *Runtime) close(retain bool) error {
if r == nil {
return nil
}
@@ -108,7 +112,7 @@ func (r *Runtime) Close() error {
drainErr := r.runPhase("drain", eligible, r.shutdown.DrainTimeout)
r.cancelWork()
r.closeErr = errors.Join(stopErr, drainErr)
if unsafePhase(stopErr) || unsafePhase(drainErr) {
if retain || unsafePhase(stopErr) || unsafePhase(drainErr) {
r.closeErr = errors.Join(r.closeErr, ErrResourcesRetained)
return
}
@@ -129,12 +133,14 @@ func runCleanup(fn func() error) (err error) {
}
// Finish closes resources and preserves the operation, cleanup and shutdown
// errors. Read the final cause only after monitors have been stopped by Close.
// errors. An incoming ErrResourcesRetained (for example, unfinished HTTP work)
// still runs stop/drain hooks, but permanently skips resource cleanup, including
// subsequent Close calls. Read the final cause after stopping the monitors.
func (r *Runtime) Finish(err error) error {
if r == nil {
return err
}
err = errors.Join(err, r.Close())
err = errors.Join(err, r.close(errors.Is(err, ErrResourcesRetained)))
if cause := r.Lifecycle.Err(); cause != nil && !errors.Is(err, cause) {
err = errors.Join(err, cause)
}