Skip to content

Commit

Permalink
Ignore duplicate transactions that occur at same time (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilayaraja89 committed Jan 11, 2018
1 parent 20d2ab8 commit 1682023
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 4 deletions.
10 changes: 10 additions & 0 deletions models/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

ledgerError "github.com/RealImage/QLedger/errors"
"github.com/lib/pq"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -132,6 +133,15 @@ func (t *TransactionDB) Transact(txn *Transaction) bool {

_, err = tx.Exec("INSERT INTO transactions (id, timestamp, data) VALUES ($1, $2, $3)", txn.ID, txn.Timestamp, transactionData)
if err != nil {
// Ignore duplicate transactions and return success response
if err.(*pq.Error).Code.Name() == "unique_violation" {
log.Println("Ignoring duplicate transaction of id:", txn.ID)
err = tx.Rollback()
if err != nil {
log.Println("Error rolling back transaction:", err)
}
return true
}
return handleTransactionError(tx, errors.Wrap(err, "insert transaction failed"))
}

Expand Down
36 changes: 34 additions & 2 deletions models/transactions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"database/sql"
"log"
"os"
"sync"
"testing"

_ "github.com/lib/pq"
Expand Down Expand Up @@ -168,9 +169,40 @@ func (ts *TransactionsModelSuite) TestTransact() {
exists, err := transactionDB.IsExists("t003")
assert.Equal(t, err, nil, "Error while checking for existing transaction")
assert.Equal(t, exists, true, "Transaction should exist")
}

func (ts *TransactionsModelSuite) TestDuplicateTransactions() {
t := ts.T()

done = transactionDB.Transact(transaction)
assert.Equal(t, done, false, "Transaction should not be created")
transactionDB := NewTransactionDB(ts.db)
transaction := &Transaction{
ID: "t005",
Lines: []*TransactionLine{
&TransactionLine{
AccountID: "a1",
Delta: 100,
},
&TransactionLine{
AccountID: "a2",
Delta: -100,
},
},
}

var wg sync.WaitGroup
wg.Add(5)
for i := 1; i <= 5; i++ {
go func(txn *Transaction) {
done := transactionDB.Transact(transaction)
assert.Equal(t, done, true, "Transaction creation should be success")
wg.Done()
}(transaction)
}
wg.Wait()

exists, err := transactionDB.IsExists("t005")
assert.Equal(t, err, nil, "Error while checking for existing transaction")
assert.Equal(t, exists, true, "Transaction should exist")
}

func (ts *TransactionsModelSuite) TestTransactWithBoundaryValues() {
Expand Down
4 changes: 2 additions & 2 deletions tests/transactions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ func RunCSVTests(accountsEndpoint string, transactionsEndpoint string, filename
localwg.Done()
}()
localwg.Wait()
if status1 == http.StatusCreated && status2 == http.StatusCreated {
log.Fatalf("Parallel repeated transactions with same ID %v are accepted", t["id"])
if (status1 != http.StatusCreated && status1 != http.StatusAccepted) || (status2 != http.StatusCreated && status2 != http.StatusAccepted) {
log.Fatalf("Parallel repeated transactions with same ID %v are not accepted", t["id"])
} else if status1 >= 400 && status2 >= 400 {
log.Fatalf("Both parallel repeated transactions with same ID %v are failed", t["id"])
}
Expand Down

0 comments on commit 1682023

Please sign in to comment.