package activator // PrepareScheduledToken orders token preparation with this host's local fence. // An admitted callback finishes before its fence is installed. Other hosts do // not wait for its IO. The callback must not reenter preparation or fencing for // the same host. This establishes neither wake nor durable maintenance authority. func (a *Service) PrepareScheduledToken(host string, prepare func() (string, error)) (string, error) { if a == nil || prepare == nil { return "", ErrFenced } for { a.mu.Lock() if a.fences[host] != 0 { a.mu.Unlock() return "", ErrFenced } if pending := a.tokenPreparations[host]; pending != nil { a.mu.Unlock() <-pending continue } if a.tokenPreparations == nil { a.tokenPreparations = make(map[string]chan struct{}) } done := make(chan struct{}) a.tokenPreparations[host] = done a.mu.Unlock() defer func() { a.mu.Lock() delete(a.tokenPreparations, host) close(done) a.mu.Unlock() }() return prepare() } }