Skip to content

Commit c605b84

Browse files
committed
refactor(core): 重构 StartWithContent 并发模型,改用互斥锁序列化并支持请求合并
- 新增 startMu + startSeq 实现并发请求 coalesce,只执行最后一个 - 配置翻译移到锁外,减小临界区 - CAS 循环简化为单次 CAS - Stop() 错误不再静默丢弃,记录日志
1 parent c710af4 commit c605b84

1 file changed

Lines changed: 20 additions & 13 deletions

File tree

core/service.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ type Service struct {
125125
platform *PlatformIO
126126
onEvent atomic.Pointer[func(int32, string)]
127127
subCancel atomic.Pointer[func()]
128+
129+
// startMu serializes StartWithContent calls. A concurrent caller waits
130+
// for the current startup to finish, then stops and restarts.
131+
startMu sync.Mutex
132+
startSeq atomic.Int64 // coalesce: only the latest caller proceeds
128133
}
129134

130135
func NewService() *Service { return &Service{platform: NewPlatformIO()} }
@@ -175,28 +180,30 @@ func (s *Service) Init(optionsJSON string) error {
175180
}
176181

177182
func (s *Service) StartWithContent(content, ruleSetProxy string) error {
183+
// Translate config outside the lock — pure computation, no shared state.
178184
data := []byte(content)
179185
jsonContent, err := s.translateConfig(data, translator.DetectFormat(data), ruleSetProxy)
180186
if err != nil {
181187
return err
182188
}
183189

184-
// CAS loop to transition to Starting — only one concurrent caller wins.
185-
for {
186-
st := s.state.Load()
187-
if st != StateInitialized && st != StateRunning {
188-
return fmt.Errorf("start: invalid state %s", st)
189-
}
190-
if s.casState(st, StateStarting) {
191-
break
192-
}
190+
mySeq := s.startSeq.Add(1)
191+
192+
s.startMu.Lock()
193+
defer s.startMu.Unlock()
194+
195+
// A newer request arrived while we waited — let it win.
196+
if s.startSeq.Load() != mySeq {
197+
return nil
193198
}
194199

195-
old := s.running.Swap(nil)
196-
s.unsubscribeHooks()
200+
// Stop any running/starting instance first.
201+
if err := s.Stop(); err != nil {
202+
slog.Warn("stop previous instance", "error", err)
203+
}
197204

198-
if old != nil {
199-
old.instance.Close()
205+
if !s.casState(StateInitialized, StateStarting) {
206+
return fmt.Errorf("start: invalid state %s", s.State())
200207
}
201208

202209
if err := s.startWithJSON(jsonContent); err != nil {

0 commit comments

Comments
 (0)