github.com/sentienttechnologies/studio-go-runner@v0.0.0-20201118202441-6d21f2ced8ee/internal/runner/singleton.go (about) 1 // Copyright 2018-2020 (c) Cognizant Digital Business, Evolutionary AI. All rights reserved. Issued under the Apache 2.0 License. 2 3 package runner 4 5 // This file contains the implementation of code that checks to ensure 6 // that the local machine only has one entity accessing a named resource. 7 // This allows callers of this code to create and test for exclusive 8 // access to resources, or to check that only one instance of a 9 // process is running. 10 11 import ( 12 "net" 13 14 "github.com/go-stack/stack" 15 "github.com/jjeffery/kv" // MIT License 16 ) 17 18 // Exclusive is a data structure used to tracking and ensure only one 19 // instance of the go runner is active on a system at once 20 // 21 type Exclusive struct { 22 Name string 23 ReleaseC chan struct{} 24 listen net.Listener 25 } 26 27 // NewExclusive is used to initialize a unix domain socket that ensure that only one 28 // runner process is active on a kubernetes pod or machine at the same time. If there 29 // are other processes active then it will return an error. 30 // 31 func NewExclusive(name string, quitC chan struct{}) (excl *Exclusive, err kv.Error) { 32 33 excl = &Exclusive{ 34 Name: name, 35 ReleaseC: quitC, 36 } 37 38 // Construct an abstract name socket that allows the name to be recycled between process 39 // restarts without needing to unlink etc. For more information please see 40 // https://gavv.github.io/blog/unix-socket-reuse/, and 41 // http://man7.org/linux/man-pages/man7/unix.7.html 42 sockName := "@/tmp/" 43 sockName += name 44 45 listen, errGo := net.Listen("unix", sockName) 46 if errGo != nil { 47 return nil, kv.Wrap(errGo).With("stack", stack.Trace().TrimRuntime()) 48 } 49 excl.listen = listen 50 51 go func() { 52 go excl.listen.Accept() 53 <-excl.ReleaseC 54 }() 55 return excl, nil 56 }