-
Notifications
You must be signed in to change notification settings - Fork 3.9k
batcher: use abstract Queue type for blocks state #12180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
5019458
op-service: add queue package
geoknee 351f708
batcher: use Queue type for blocks
geoknee 5dc3228
revert changes to errors.As/Is
geoknee 2a1a63d
implement and use Peek operation
geoknee f3af344
queue: add unit tests
geoknee 4690bd6
add godoc
geoknee 9cec043
add more test cases
geoknee ffc238c
ensure enqueue and prepend are noops when args is empty
geoknee 6c2c349
use queue.PeekN and queue.DequeueN
geoknee 6a5c698
typo
geoknee 65882d9
queue: simplify method implementations
geoknee eff70e5
revert to old dequeue impl
geoknee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| package queue | ||
sebastianst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Queue implements a FIFO queue. | ||
| type Queue[T any] []T | ||
geoknee marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Enqueue adds the elements to the back of the queue. | ||
| func (q *Queue[T]) Enqueue(t ...T) { | ||
| if len(t) == 0 { | ||
| return | ||
| } | ||
| *q = append(*q, t...) | ||
| } | ||
|
|
||
| // Dequeue removes a single element from the front of the queue | ||
| // (if there is one) and returns it. Returns a zero value and false | ||
| // if there is no element to dequeue. | ||
| func (q *Queue[T]) Dequeue() (T, bool) { | ||
| if len(*q) == 0 { | ||
| var zeroValue T | ||
| return zeroValue, false | ||
| } | ||
| t := (*q)[0] | ||
| *q = (*q)[1:] | ||
| return t, true | ||
sebastianst marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| // DequeueN removes N elements from the front of the queue | ||
| // (if there are enough) and returns a slice of those elements. Returns | ||
| // a nil slice and false if there are insufficient elements to dequeue. | ||
| func (q *Queue[T]) DequeueN(N int) ([]T, bool) { | ||
| if len(*q) < N { | ||
| return nil, false | ||
| } | ||
| t := (*q)[0:N] | ||
| *q = (*q)[N:] | ||
| return t, true | ||
| } | ||
|
|
||
| // Prepend inserts the elements at the front of the queue, | ||
| // preserving their order. A noop if t is empty. | ||
| func (q *Queue[T]) Prepend(t ...T) { | ||
| if len(t) == 0 { | ||
| return | ||
| } | ||
| *q = append(t, *q...) | ||
| } | ||
|
|
||
| // Clear removes all elements from the queue. | ||
| func (q *Queue[T]) Clear() { | ||
| *q = (*q)[:0] | ||
| } | ||
|
|
||
| // Len returns the number of elements in the queue. | ||
| func (q *Queue[T]) Len() int { | ||
| return len(*q) | ||
| } | ||
|
|
||
| // Peek returns the single element at the front of the queue | ||
| // (if there is one) without removing it. Returns a zero value and | ||
| // false if there is no element to peek at. | ||
| func (q *Queue[T]) Peek() (T, bool) { | ||
| return q.PeekN(0) | ||
| } | ||
|
|
||
| // PeekN returns the element in Nth position in the queue | ||
| // Returns a zero value and false if there are insufficient elements | ||
| // in the queue. | ||
| func (q *Queue[T]) PeekN(N int) (T, bool) { | ||
| if len(*q) <= N { | ||
| var zeroValue T | ||
| return zeroValue, false | ||
| } | ||
| t := (*q)[N] | ||
| return t, true | ||
| } | ||
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| package queue | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestQueue(t *testing.T) { | ||
| t.Run("enqueue amd dequeue", func(t *testing.T) { | ||
| q := Queue[int]{} | ||
| q.Enqueue(1, 2, 3, 4) | ||
|
|
||
| p, peekOk := q.Peek() | ||
| require.True(t, peekOk) | ||
| require.Equal(t, 1, p) | ||
|
|
||
| d, dequeueOk := q.Dequeue() | ||
| require.Equal(t, 1, d) | ||
| require.True(t, dequeueOk) | ||
| require.Equal(t, 3, q.Len()) | ||
| p, peekOk = q.Peek() | ||
| require.True(t, peekOk) | ||
| require.Equal(t, 2, p) | ||
|
|
||
| d, dequeueOk = q.Dequeue() | ||
| require.Equal(t, 2, d) | ||
| require.True(t, dequeueOk) | ||
| require.Equal(t, 2, q.Len()) | ||
| p, peekOk = q.Peek() | ||
| require.True(t, peekOk) | ||
| require.Equal(t, 3, p) | ||
|
|
||
| d, dequeueOk = q.Dequeue() | ||
| require.Equal(t, 3, d) | ||
| require.True(t, dequeueOk) | ||
| require.Equal(t, 1, q.Len()) | ||
| p, peekOk = q.Peek() | ||
| require.True(t, peekOk) | ||
| require.Equal(t, 4, p) | ||
|
|
||
| d, dequeueOk = q.Dequeue() | ||
| require.Equal(t, 4, d) | ||
| require.True(t, dequeueOk) | ||
| require.Equal(t, 0, q.Len()) | ||
| p, peekOk = q.Peek() | ||
| require.False(t, peekOk) | ||
| require.Equal(t, 0, p) | ||
|
|
||
| d, dequeueOk = q.Dequeue() | ||
| require.Equal(t, 0, d) | ||
| require.False(t, dequeueOk) | ||
| require.Equal(t, 0, q.Len()) | ||
| p, peekOk = q.Peek() | ||
| require.False(t, peekOk) | ||
| require.Equal(t, 0, p) | ||
| p, peekOk = q.Peek() | ||
| require.False(t, peekOk) | ||
| require.Equal(t, 0, p) | ||
| }) | ||
|
|
||
| t.Run("peekN and deqeueueN", func(t *testing.T) { | ||
| q := Queue[int]{} | ||
| q.Enqueue(1, 2, 3, 4) | ||
|
|
||
| p, peekOk := q.PeekN(1) | ||
| require.True(t, peekOk) | ||
| require.Equal(t, 2, p) | ||
|
|
||
| p, peekOk = q.PeekN(2) | ||
| require.Equal(t, 3, p) | ||
| require.True(t, peekOk) | ||
| require.Equal(t, 4, q.Len()) | ||
|
|
||
| p, peekOk = q.PeekN(4) | ||
| require.Equal(t, 0, p) | ||
| require.False(t, peekOk) | ||
|
|
||
| d, dequeueOk := q.DequeueN(1) | ||
| require.Equal(t, []int{1}, d) | ||
| require.True(t, dequeueOk) | ||
| require.Equal(t, 3, q.Len()) | ||
|
|
||
| d, dequeueOk = q.DequeueN(3) | ||
| require.Equal(t, []int{2, 3, 4}, d) | ||
| require.True(t, dequeueOk) | ||
| require.Equal(t, 0, q.Len()) | ||
| }) | ||
|
|
||
| t.Run("enqueue and clear", func(t *testing.T) { | ||
| q := Queue[int]{} | ||
| q.Enqueue(5, 6, 7) | ||
|
|
||
| q.Clear() | ||
| require.Equal(t, 0, q.Len()) | ||
|
|
||
| d, ok := q.Dequeue() | ||
| require.Equal(t, 0, d) | ||
| require.False(t, ok) | ||
| }) | ||
|
|
||
| t.Run("prepend", func(t *testing.T) { | ||
| var q, r Queue[int] | ||
| q.Enqueue(5, 6, 7) | ||
| r.Enqueue(8, 9) | ||
|
|
||
| q.Prepend(r...) | ||
| require.Equal(t, 5, q.Len()) | ||
|
|
||
| d, ok := q.Dequeue() | ||
| require.Equal(t, 8, d) | ||
| require.True(t, ok) | ||
| require.Equal(t, 4, q.Len()) | ||
|
|
||
| q.Prepend() | ||
| require.Equal(t, 4, q.Len()) | ||
|
|
||
| d, ok = q.Dequeue() | ||
| require.Equal(t, 9, d) | ||
| require.True(t, ok) | ||
| }) | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.