-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Write into PostgreSQL, implemented mutex and added unit tests
- Loading branch information
1 parent
b67b87a
commit e03479a
Showing
5 changed files
with
257 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
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,61 @@ | ||
package processor | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
"sync" | ||
|
||
"github.com/arturogonzalezm/RealTimeBinanceMonitor/internal/models" | ||
) | ||
|
||
// PGWriter implements DataProcessor interface for PostgreSQL | ||
type PGWriter struct { | ||
db *sql.DB | ||
mutex sync.Mutex | ||
processedCount int | ||
} | ||
|
||
// NewPGWriter creates a new PGWriter | ||
func NewPGWriter(db *sql.DB) (*PGWriter, error) { | ||
writer := &PGWriter{ | ||
db: db, | ||
} | ||
|
||
return writer, nil | ||
} | ||
|
||
// Process implements the DataProcessor interface | ||
func (w *PGWriter) Process(data models.FormattedData) { | ||
w.mutex.Lock() | ||
defer w.mutex.Unlock() | ||
|
||
_, err := w.db.Exec(`INSERT INTO ticker_data ( | ||
event_time, symbol, last_price, price_change, high_price, low_price, volume, quote_volume, open_time, close_time, trade_count, latency | ||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, | ||
data.EventTime, data.Symbol, data.LastPrice, data.PriceChange, data.HighPrice, data.LowPrice, | ||
data.Volume, data.QuoteVolume, data.OpenTime, data.CloseTime, data.TradeCount, data.Latency, | ||
) | ||
if err != nil { | ||
fmt.Printf("Error inserting data: %v\n", err) | ||
return | ||
} | ||
|
||
w.processedCount++ | ||
} | ||
|
||
// GetProcessedCount returns the number of processed messages | ||
func (w *PGWriter) GetProcessedCount() int { | ||
w.mutex.Lock() | ||
defer w.mutex.Unlock() | ||
return w.processedCount | ||
} | ||
|
||
// GetBufferSize returns the current size of the buffer (always 0 for immediate insert) | ||
func (w *PGWriter) GetBufferSize() int { | ||
return 0 | ||
} | ||
|
||
// Close closes the PostgreSQL connection | ||
func (w *PGWriter) Close() error { | ||
return w.db.Close() | ||
} |
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,117 @@ | ||
package processor | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/DATA-DOG/go-sqlmock" | ||
"github.com/arturogonzalezm/RealTimeBinanceMonitor/internal/models" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNewPGWriter(t *testing.T) { | ||
db, mock, err := sqlmock.New() | ||
assert.NoError(t, err) | ||
defer func() { | ||
mock.ExpectClose() | ||
err := db.Close() | ||
assert.NoError(t, err) | ||
assert.NoError(t, mock.ExpectationsWereMet()) | ||
}() | ||
|
||
writer, err := NewPGWriter(db) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, writer) | ||
} | ||
|
||
func TestPGWriter_Process(t *testing.T) { | ||
db, mock, err := sqlmock.New() | ||
assert.NoError(t, err) | ||
defer func() { | ||
mock.ExpectClose() | ||
err := db.Close() | ||
assert.NoError(t, err) | ||
assert.NoError(t, mock.ExpectationsWereMet()) | ||
}() | ||
|
||
writer, err := NewPGWriter(db) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, writer) | ||
|
||
data := models.FormattedData{ | ||
EventTime: 1625097600000, | ||
Symbol: "btcusdt", | ||
LastPrice: 34000.0, | ||
PriceChange: 100.0, | ||
HighPrice: 34500.0, | ||
LowPrice: 33500.0, | ||
Volume: 100.0, | ||
QuoteVolume: 3400000.0, | ||
OpenTime: 1625094000000, | ||
CloseTime: 1625097600000, | ||
TradeCount: 1000, | ||
Latency: 100, | ||
} | ||
|
||
mock.ExpectExec(`INSERT INTO ticker_data`). | ||
WithArgs( | ||
data.EventTime, data.Symbol, data.LastPrice, data.PriceChange, data.HighPrice, data.LowPrice, | ||
data.Volume, data.QuoteVolume, data.OpenTime, data.CloseTime, data.TradeCount, data.Latency, | ||
). | ||
WillReturnResult(sqlmock.NewResult(1, 1)) | ||
|
||
writer.Process(data) | ||
|
||
assert.Equal(t, 1, writer.GetProcessedCount()) | ||
} | ||
|
||
func TestPGWriter_GetProcessedCount(t *testing.T) { | ||
db, mock, err := sqlmock.New() | ||
assert.NoError(t, err) | ||
defer func() { | ||
mock.ExpectClose() | ||
err := db.Close() | ||
assert.NoError(t, err) | ||
assert.NoError(t, mock.ExpectationsWereMet()) | ||
}() | ||
|
||
writer, err := NewPGWriter(db) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, writer) | ||
|
||
assert.Equal(t, 0, writer.GetProcessedCount()) | ||
} | ||
|
||
func TestPGWriter_GetBufferSize(t *testing.T) { | ||
db, mock, err := sqlmock.New() | ||
assert.NoError(t, err) | ||
defer func() { | ||
mock.ExpectClose() | ||
err := db.Close() | ||
assert.NoError(t, err) | ||
assert.NoError(t, mock.ExpectationsWereMet()) | ||
}() | ||
|
||
writer, err := NewPGWriter(db) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, writer) | ||
|
||
assert.Equal(t, 0, writer.GetBufferSize()) | ||
} | ||
|
||
func TestPGWriter_Close(t *testing.T) { | ||
db, mock, err := sqlmock.New() | ||
assert.NoError(t, err) | ||
defer func() { | ||
assert.NoError(t, mock.ExpectationsWereMet()) | ||
}() | ||
|
||
writer, err := NewPGWriter(db) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, writer) | ||
|
||
mock.ExpectClose() | ||
|
||
err = writer.Close() | ||
assert.NoError(t, err) | ||
assert.NoError(t, mock.ExpectationsWereMet()) | ||
} |