You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Current implements of function Close is not graceful, which just sets a closed mark and returns, but the goroutine jobs are still running in background. We need wait all goroutine or wait current jobs done before exit the process when receiving shutdown signals.
Describe alternatives you've considered
Features we considered:
1. Configurable Shutdown Options
Introduce shutdown options that allow users to:
Wait for currently executing tasks to complete before shutdown
Wait for all queued tasks to complete before shutdown
Implement blocking shutdown mechanism to ensure proper cleanup
2. Signal Handling
Add built-in signal handling capabilities:
Automatic monitoring of system shutdown signals
Graceful shutdown initiation upon signal reception
Signal handling configuration available during pool creation
Additional
Here are the codes that AI suggests:
// ShutdownOption defines the configuration for graceful shutdowntypeShutdownOptionstruct {
// WaitForRunningJobs indicates whether to wait for currently running jobs to completeWaitForRunningJobsbool// WaitForQueuedJobs indicates whether to wait for all queued jobs to completeWaitForQueuedJobsbool// HandleSignals indicates whether to automatically handle system signals for graceful shutdownHandleSignalsbool
}
// PoolOption defines the configuration for pool creationtypePoolOptionstruct {
// Limit sets the maximum number of goroutinesLimitint// ShutdownOption configures the graceful shutdown behaviorShutdown*ShutdownOption
}
{{ ... }}
// ShutdownOption defines the configuration for graceful shutdowntypeShutdownOptionstruct {
// WaitForRunningJobs indicates whether to wait for currently running jobs to completeWaitForRunningJobsbool// WaitForQueuedJobs indicates whether to wait for all queued jobs to completeWaitForQueuedJobsbool// HandleSignals indicates whether to automatically handle system signals for graceful shutdownHandleSignalsbool
}
// PoolOption defines the configuration for pool creationtypePoolOptionstruct {
// Limit sets the maximum number of goroutinesLimitint// ShutdownOption configures the graceful shutdown behaviorShutdown*ShutdownOption
}
// Pool manages the goroutines using pool.typePoolstruct {
limitint// Max goroutine count limit.count*gtype.Int// Current running goroutine count.list*glist.List// List for asynchronous job adding purpose.closed*gtype.Bool// Is pool closed or not.shutdownOpt*ShutdownOption// Shutdown optionsrunningJobs*gtype.Int// Current running job countshutdownChanchanstruct{} // Channel for shutdown signalshutdownDonechanstruct{} // Channel to signal shutdown completion
}
{{ ... }}
{{ ... }}
// New creates and returns a new goroutine pool object.// The parameter `option` is used to configure the pool.funcNew(option...*PoolOption) *Pool {
var (
pool=&Pool{
limit: -1,
count: gtype.NewInt(),
list: glist.New(true),
closed: gtype.NewBool(),
runningJobs: gtype.NewInt(),
shutdownChan: make(chanstruct{}),
shutdownDone: make(chanstruct{}),
shutdownOpt: &ShutdownOption{},
}
timerDuration=grand.D(
minSupervisorTimerDuration,
maxSupervisorTimerDuration,
)
)
// Apply options if providediflen(option) >0&&option[0] !=nil {
ifoption[0].Limit>0 {
pool.limit=option[0].Limit
}
ifoption[0].Shutdown!=nil {
pool.shutdownOpt=option[0].Shutdown
}
}
// Start supervisorgtimer.Add(context.Background(), timerDuration, pool.supervisor)
// Setup signal handling if enabledifpool.shutdownOpt.HandleSignals {
gopool.handleSignals()
}
returnpool
}
{{ ... }}
{{ ... }}
import (
"os""os/signal""syscall""time"
)
// handleSignals handles system signals for graceful shutdownfunc (p*Pool) handleSignals() {
sigChan:=make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
<-sigChan_=p.Shutdown()
}
// Shutdown initiates a graceful shutdown of the poolfunc (p*Pool) Shutdown() error {
// Prevent multiple shutdownsif!p.closed.Cas(false, true) {
returngerror.NewCode(
gcode.CodeInvalidOperation,
"pool is already shutting down",
)
}
// Close shutdown channel to notify all workersclose(p.shutdownChan)
// If we don't need to wait for any jobs, return immediatelyif!p.shutdownOpt.WaitForRunningJobs&&!p.shutdownOpt.WaitForQueuedJobs {
close(p.shutdownDone)
returnnil
}
// Wait for running jobs if requiredifp.shutdownOpt.WaitForRunningJobs {
forp.runningJobs.Val() >0 {
time.Sleep(100*time.Millisecond)
}
}
// Wait for queued jobs if requiredifp.shutdownOpt.WaitForQueuedJobs {
forp.list.Size() >0||p.runningJobs.Val() >0 {
time.Sleep(100*time.Millisecond)
}
}
close(p.shutdownDone)
returnnil
}
// WaitForShutdown blocks until the pool has been shut downfunc (p*Pool) WaitForShutdown() {
<-p.shutdownDone
}
{{ ... }}
{{ ... }}
// Add pushes a new job to the pool.func (p*Pool) Add(ctx context.Context, fFunc) error {
ifp.closed.Val() {
returngerror.NewCode(
gcode.CodeInvalidOperation,
"goroutine pool is closed",
)
}
p.list.PushFront(&localPoolItem{
Ctx: ctx,
Func: f,
})
// Check and fork new worker.p.checkAndForkNewGoroutineWorker()
returnnil
}
// checkAndForkNewGoroutineWorker checks and creates a new goroutine worker.func (p*Pool) checkAndForkNewGoroutineWorker() {
varnintfor {
n=p.count.Val()
ifp.limit!=-1&&n>=p.limit {
return
}
ifp.count.Cas(n, n+1) {
break
}
}
gofunc() {
deferp.count.Add(-1)
for {
ifp.closed.Val() &&p.list.Size() ==0 {
return
}
v:=p.list.PopBack()
ifv==nil {
return
}
item:=v.(*localPoolItem)
p.runningJobs.Add(1)
item.Func(item.Ctx)
p.runningJobs.Add(-1)
// Check if we should exitselect {
case<-p.shutdownChan:
// If we're shutting down and not waiting for queued jobs, exitif!p.shutdownOpt.WaitForQueuedJobs {
return
}
default:
}
}
}()
}
{{ ... }}
The text was updated successfully, but these errors were encountered:
Is your feature request related to a problem?
Option No
Describe the solution you'd like
Current implements of function
Close
is not graceful, which just sets a closed mark and returns, but the goroutine jobs are still running in background. We need wait all goroutine or wait current jobs done before exit the process when receiving shutdown signals.Describe alternatives you've considered
Features we considered:
1. Configurable Shutdown Options
Introduce shutdown options that allow users to:
2. Signal Handling
Add built-in signal handling capabilities:
Additional
Here are the codes that AI suggests:
The text was updated successfully, but these errors were encountered: