github.com/gedevops/x@v1.0.3/watcherx/definitions.go (about) 1 package watcherx 2 3 import ( 4 "context" 5 "fmt" 6 "net/url" 7 ) 8 9 type ( 10 errSchemeUnknown struct { 11 scheme string 12 } 13 EventChannel chan Event 14 Watcher interface { 15 // DispatchNow fires the watcher and causes an event. 16 // 17 // WARNING: The returned channel must be read or no further events will 18 // be propagated due to a deadlock. 19 DispatchNow() (<-chan int, error) 20 } 21 dispatcher struct { 22 trigger chan struct{} 23 done chan int 24 } 25 ) 26 27 var ( 28 // ErrSchemeUnknown is just for checking with errors.Is() 29 ErrSchemeUnknown = &errSchemeUnknown{} 30 ErrWatcherNotRunning = fmt.Errorf("watcher is not running") 31 ) 32 33 func (e *errSchemeUnknown) Is(other error) bool { 34 _, ok := other.(*errSchemeUnknown) 35 return ok 36 } 37 38 func (e *errSchemeUnknown) Error() string { 39 return fmt.Sprintf("unknown scheme '%s' to watch", e.scheme) 40 } 41 42 func newDispatcher() *dispatcher { 43 return &dispatcher{ 44 trigger: make(chan struct{}), 45 done: make(chan int), 46 } 47 } 48 49 func (d *dispatcher) DispatchNow() (<-chan int, error) { 50 if d.trigger == nil { 51 return nil, ErrWatcherNotRunning 52 } 53 d.trigger <- struct{}{} 54 return d.done, nil 55 } 56 57 func Watch(ctx context.Context, u *url.URL, c EventChannel) (Watcher, error) { 58 switch u.Scheme { 59 // see urlx.Parse for why the empty string is also file 60 case "file", "": 61 return WatchFile(ctx, u.Path, c) 62 case "ws": 63 return WatchWebsocket(ctx, u, c) 64 } 65 return nil, &errSchemeUnknown{u.Scheme} 66 }