github.com/blend/go-sdk@v1.20220411.3/cmd/fslock/main.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package main 9 10 import ( 11 "context" 12 "flag" 13 "fmt" 14 "os" 15 "time" 16 17 "github.com/blend/go-sdk/filelock" 18 ) 19 20 var ( 21 flagExclusive = flag.Bool("exclusive", false, "If the lock is exclusive or not") 22 flagRemove = flag.Bool("remove", false, "If the lock file should be removed when complete") 23 flagWaitFor = flag.Duration("wait-for", 10*time.Second, "The duration to hold the lock for") 24 flagHoldFor = flag.Duration("hold-for", 10*time.Second, "The duration to hold the lock for") 25 ) 26 27 func init() { 28 flag.Parse() 29 } 30 31 func main() { 32 filePath := flag.Arg(0) 33 if filePath == "" { 34 fmt.Fprintf(os.Stderr, "Must provide a filepath; see usage for details") 35 os.Exit(1) 36 } 37 38 mu := filelock.MutexAt(filePath) 39 40 var lockfn func() (func(), error) 41 if *flagExclusive { 42 lockfn = mu.Lock 43 } else { 44 lockfn = mu.RLock 45 } 46 47 unlock, err := waitAcquired(lockfn, *flagWaitFor) 48 if err != nil { 49 fmt.Fprintf(os.Stderr, "Error acquiring lock for file %q; %+v\n", filePath, err) 50 os.Exit(1) 51 } 52 defer func() { 53 unlock() 54 if *flagRemove { 55 fmt.Println("Removing lock file", filePath) 56 _ = os.Remove(filePath) 57 } 58 }() 59 60 fmt.Println("Acquired lock", filePath, "holding for", *flagHoldFor) 61 <-time.After(*flagHoldFor) 62 } 63 64 func waitAcquired(lockfn func() (func(), error), waitFor time.Duration) (unlock func(), err error) { 65 finished := make(chan struct{}) 66 go func() { 67 defer close(finished) 68 unlock, err = lockfn() 69 }() 70 select { 71 case <-finished: 72 return 73 case <-time.After(waitFor): 74 err = context.Canceled 75 return 76 } 77 }