From 6097361fc47a361800ad35a11d6fe3719b2ae0a4 Mon Sep 17 00:00:00 2001 From: Kevin Keuning Date: Fri, 14 Apr 2017 15:29:21 -0500 Subject: improved throttle to ensure content is sorted --- system/db/content.go | 59 ++++++++++++++++++++++++++++++---------------------- 1 file 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 } -- cgit v1.2.3 From 19c8b41621a73d19ba74f3b2fc82ae53206d242c Mon Sep 17 00:00:00 2001 From: Kevin Keuning Date: Fri, 14 Apr 2017 16:18:12 -0500 Subject: simpler throttle --- system/db/content.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/system/db/content.go b/system/db/content.go index e573e79..b503a60 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -600,16 +600,15 @@ func enoughTime(key string) bool { // 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) - } + lastInvocationBeforeTimer, _ := lastInvocation(key) // zero value can be handled, no need for ok + enoughTimer := time.NewTimer(waitDuration) + <-enoughTimer.C + lastInvocationAfterTimer, _ := lastInvocation(key) + if !lastInvocationAfterTimer.After(lastInvocationBeforeTimer) { + SortContent(key) } }() + return false } -- cgit v1.2.3