diff options
author | Kevin Keuning <kkeuning@gmail.com> | 2017-04-14 15:29:21 -0500 |
---|---|---|
committer | Kevin Keuning <kkeuning@gmail.com> | 2017-04-14 15:29:21 -0500 |
commit | 6097361fc47a361800ad35a11d6fe3719b2ae0a4 (patch) | |
tree | 64629a9323ea008d7f6a487b6a06741b195dde24 | |
parent | 55f18eedc3ecda2154df657edbe5d3e62eb22734 (diff) |
improved throttle to ensure content is sorted
-rw-r--r-- | system/db/content.go | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/system/db/content.go b/system/db/content.go index b3e2642..e573e79 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -9,6 +9,7 @@ import ( "sort" "strconv" "strings" + "sync" "time" "github.com/ponzu-cms/ponzu/system/item" @@ -567,41 +568,49 @@ func Query(namespace string, opts QueryOptions) (int, [][]byte) { var sortContentCalls = make(map[string]time.Time) var waitDuration = time.Millisecond * 2000 +var sortMutex = &sync.Mutex{} -func enoughTime(key string, withDelay bool) bool { +func setLastInvocation(key string) { + sortMutex.Lock() + sortContentCalls[key] = time.Now() + sortMutex.Unlock() +} + +func lastInvocation(key string) (time.Time, bool) { + sortMutex.Lock() last, ok := sortContentCalls[key] + sortMutex.Unlock() + return last, ok +} + +func enoughTime(key string) bool { + last, ok := lastInvocation(key) if !ok { // no invocation yet // track next invocation - sortContentCalls[key] = time.Now() + setLastInvocation(key) return true } - // if our required wait time has not been met, return false - if !time.Now().After(last.Add(waitDuration)) { - return false + // if our required wait time has been met, return true + if time.Now().After(last.Add(waitDuration)) { + setLastInvocation(key) + return true } - // dispatch a delayed envocation in case no additional one follows - if withDelay { - go func() { - select { - case <-time.After(waitDuration): - if enoughTime(key, false) { - // track next invocation - sortContentCalls[key] = time.Now() - SortContent(key) - } else { - // retrigger - SortContent(key) - } + // dispatch a delayed invocation in case no additional one follows + go func() { + lastInvocationBeforeTicker, _ := lastInvocation(key) // zero value can be handled, no need for ok + enoughTicker := time.NewTicker(waitDuration) + select { + case <-enoughTicker.C: + lastInvocationAfterTicker, _ := lastInvocation(key) + if !lastInvocationAfterTicker.After(lastInvocationBeforeTicker) { + SortContent(key) } - }() - } - - // track next invocation - sortContentCalls[key] = time.Now() - return true + } + }() + return false } // SortContent sorts all content of the type supplied as the namespace by time, @@ -609,7 +618,7 @@ func enoughTime(key string, withDelay bool) bool { // Should be called from a goroutine after SetContent is successful func SortContent(namespace string) { // wait if running too frequently per namespace - if !enoughTime(namespace, true) { + if !enoughTime(namespace) { return } |