-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f6b742b
commit a8c8a43
Showing
12 changed files
with
177 additions
and
49 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package writer | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log/slog" | ||
"time" | ||
|
||
"github.com/artie-labs/reader/destinations" | ||
"github.com/artie-labs/reader/lib" | ||
) | ||
|
||
type RawMessageIterator interface { | ||
HasNext() bool | ||
Next() ([]lib.RawMessage, error) | ||
} | ||
|
||
type Writer struct { | ||
destination destinations.Destination | ||
} | ||
|
||
func New(destination destinations.Destination) Writer { | ||
return Writer{destination} | ||
} | ||
|
||
// Write writes all the messages from an iterator to the destination. | ||
func (w *Writer) Write(ctx context.Context, iter RawMessageIterator) (int, error) { | ||
start := time.Now() | ||
var count int | ||
for iter.HasNext() { | ||
msgs, err := iter.Next() | ||
if err != nil { | ||
return 0, fmt.Errorf("failed to iterate over messages: %w", err) | ||
|
||
} else if len(msgs) > 0 { | ||
if err = w.destination.WriteRawMessages(ctx, msgs); err != nil { | ||
return 0, fmt.Errorf("failed to write messages: %w", err) | ||
} | ||
count += len(msgs) | ||
} | ||
slog.Info("Write progress", | ||
slog.Duration("timing", time.Since(start)), | ||
slog.Int("batchSize", len(msgs)), | ||
slog.Int("total", count), | ||
) | ||
} | ||
return count, nil | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package writer | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/artie-labs/reader/lib" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
type mockDestination struct { | ||
messages []lib.RawMessage | ||
emitError bool | ||
} | ||
|
||
func (m *mockDestination) WriteRawMessages(ctx context.Context, msgs []lib.RawMessage) error { | ||
if m.emitError { | ||
return fmt.Errorf("test write raw messages error") | ||
} | ||
m.messages = append(m.messages, msgs...) | ||
return nil | ||
} | ||
|
||
type mockIterator struct { | ||
emitError bool | ||
index int | ||
batches [][]lib.RawMessage | ||
} | ||
|
||
func (m *mockIterator) HasNext() bool { | ||
return m.index < len(m.batches) | ||
} | ||
|
||
func (m *mockIterator) Next() ([]lib.RawMessage, error) { | ||
if m.emitError { | ||
return nil, fmt.Errorf("test iteration error") | ||
} | ||
|
||
if !m.HasNext() { | ||
return nil, fmt.Errorf("done") | ||
} | ||
result := m.batches[m.index] | ||
m.index++ | ||
return result, nil | ||
} | ||
|
||
func TestWriter_Write(t *testing.T) { | ||
{ | ||
// Empty iterator | ||
destination := &mockDestination{} | ||
writer := New(destination) | ||
iterator := &mockIterator{} | ||
count, err := writer.Write(context.Background(), iterator) | ||
assert.NoError(t, err) | ||
assert.Equal(t, 0, count) | ||
assert.Empty(t, destination.messages) | ||
} | ||
{ | ||
// Iteration error | ||
destination := &mockDestination{} | ||
writer := New(destination) | ||
iterator := &mockIterator{emitError: true, batches: [][]lib.RawMessage{{{TopicSuffix: "a"}}}} | ||
_, err := writer.Write(context.Background(), iterator) | ||
assert.ErrorContains(t, err, "failed to iterate over messages: test iteration error") | ||
assert.Empty(t, destination.messages) | ||
} | ||
{ | ||
// Two empty batches | ||
destination := &mockDestination{} | ||
writer := New(destination) | ||
iterator := &mockIterator{batches: [][]lib.RawMessage{{}, {}}} | ||
count, err := writer.Write(context.Background(), iterator) | ||
assert.NoError(t, err) | ||
assert.Equal(t, 0, count) | ||
assert.Empty(t, destination.messages) | ||
} | ||
{ | ||
// Three batches, two non-empty | ||
destination := &mockDestination{} | ||
writer := New(destination) | ||
iterator := &mockIterator{batches: [][]lib.RawMessage{{{TopicSuffix: "a"}}, {}, {{TopicSuffix: "b"}, {TopicSuffix: "c"}}}} | ||
count, err := writer.Write(context.Background(), iterator) | ||
assert.NoError(t, err) | ||
assert.Equal(t, 3, count) | ||
assert.Len(t, destination.messages, 3) | ||
} | ||
{ | ||
// Destionation error | ||
destination := &mockDestination{emitError: true} | ||
writer := New(destination) | ||
iterator := &mockIterator{batches: [][]lib.RawMessage{{{TopicSuffix: "a"}}}} | ||
_, err := writer.Write(context.Background(), iterator) | ||
assert.ErrorContains(t, err, "failed to write messages: test write raw messages error") | ||
assert.Empty(t, destination.messages) | ||
} | ||
} |
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
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
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
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
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
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
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
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