Last active
January 13, 2019 00:46
-
-
Save rjeczalik/7faa93691e6da35b1f84 to your computer and use it in GitHub Desktop.
queued watch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"os" | |
"sync" | |
"github.com/rjeczalik/notify" | |
) | |
func main() { | |
c, err := QueuedWatch(".", notify.All) | |
if err != nil { | |
log.Fatalln(err) | |
} | |
for ev := range c { | |
log.Println(os.Args[0], ev) | |
} | |
} | |
func QueuedWatch(path string, events ...notify.Event) (chan notify.EventInfo, error) { | |
in := make(chan notify.EventInfo, 10240) | |
err := notify.Watch(path, in, events...) | |
if err != nil { | |
return nil, err | |
} | |
out := make(chan notify.EventInfo) | |
queueEvents(in, out) | |
return out, nil | |
} | |
type eventQueue struct { | |
mu sync.Mutex | |
queue []notify.EventInfo | |
sleep chan struct{} | |
} | |
func queueEvents(in, out chan notify.EventInfo) { | |
ev := &eventQueue{ | |
sleep: make(chan struct{}, 1), | |
} | |
go ev.enqueueLoop(in) | |
go ev.popLoop(out) | |
} | |
func (eq *eventQueue) enqueueLoop(in chan notify.EventInfo) { | |
var sleeping bool | |
for ev := range in { | |
eq.mu.Lock() | |
sleeping = len(eq.queue) == 0 | |
eq.queue = append(eq.queue, ev) | |
if sleeping { | |
select { | |
case eq.sleep <- struct{}{}: | |
default: | |
} | |
} | |
eq.mu.Unlock() | |
} | |
} | |
func (eq *eventQueue) pop() (ev notify.EventInfo, n int) { | |
eq.mu.Lock() | |
defer eq.mu.Unlock() | |
if n = len(eq.queue); n == 0 { | |
return nil, 0 | |
} | |
ev, eq.queue = eq.queue[0], eq.queue[1:] | |
return ev, n | |
} | |
func (eq *eventQueue) popLoop(out chan notify.EventInfo) { | |
var ev notify.EventInfo | |
var n int | |
for range eq.sleep { | |
for ev, n = eq.pop(); n != 0; ev, n = eq.pop() { | |
out <- ev | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @sent-hil, I've verified it on a Koding VM, my
QueuedWatch
just needs bigger inner-buffer (I've updated the above gist with 10240).You can verify if there're dropped events - build the binary with
debug
tag, e.g.:Then the library will log to stderr any dropped events:
I'll see if we can add a buffering to the notify API to do it for the user, for now you'll need to keep bumping the buffer yourself :)