EdwinRy / Transactions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Transactions

This project implements a sample transaction processing engine which takes in a CSV file for its input of transactions and outputs the current state of user accounts based on the transactions carried out.

Quick Start

For it's lack of release, only operations through cargo are supported. Be sure to clone the repository, then from the project root run

cargo run <input-file>

Where <input-file> is the path to the CSV file to process, the root of the repository contains example.csv to quickly test out the program.

Design overview

Source Structure

As the program launches, it reads the first command line argument (outside of program name) to get the path of the data file to process, The reader implements a generator pattern to more closely replicate a queue-based approach to processing data with the possibility of easily swapping out the data source.

Each row of the CSV file (apart from header) is parsed into a Transaction object, each transaction object stores: the kind of transaction represented, ID if the client to which the transaction related, the transaction ID which stores either the ID of the current transaction (deposit) or the ID of the transaction affected by the currently parsed line.

Execution of each transaction requires a reference to a store - a store is a struct of HashMaps which provides fast access to currently stored clients and transactions in memory. The store closely mimics a pattern used for external data store access (ORM etc) so that the code can be relatively easily adapted for use with external storage which would be preferable for processing much larger amounts of data.

Once all transactions are processed the store reads all client records and outputs all of it in a table format.

Processing Data

Currency

Currently, the program does not recognise currencies, but simply deals with high precision decimal values provided with the rust_decimal library, the library implementation of decimal point math eliminated typical float related errors.

Client Total

The specification calls for a total property to be generated by the code. This is done lazily as it's much more common for transactions to update client balance than it is for the client record to be displayed - hence we can save a few operations by only doing them when necessary, this also simplifies some of maths so that the available funds, held funds and the total are always bound together.

Transactions

The specification omits a few necessary requirements for the implementation of certain transactions:

Only transaction kinds which have their own "primary key" are deposits and withdrawals, because the "tx" column is used for referencing other transactions in case of chargebacks, resolves, and disputes. In production we might want to have a primary key for all transactions so that we can make amendments if necessary.

There might be several cases where some transactions fail, the specification doesn't include requirements for handling those failed transactions, current implementation simply ignores them, but it might be good to have a failed queue system which would require each transaction to have it's own primary key and a timestamp.

Charge backs and Resolutions also refer only to the original transactions, there is currently no way of handling multiple (erroneous) resolutions and chargebacks for a single transactions, it might be a good idea for both charge backs and resolutions to link to a dispute.

Multithreading

In an event where data comes live through multiple different sources it would make sense to use threading for handling transactions, the existing structure could be easily adapted as long as the store is replaced to use thread safe storage.

Multithreading might also become a necessity if there is too much data for a single processor to process in a reasonable amount of time.

Testing

Unit Tests

Unit tests are contained at the bottom of each source file compiled only with cargo test, the tests cover a range of use cases for code containing logic beyond wrapping 3rd party provided functions.

Integration Tests

Integration tests are included within the src/ folder, in the tests.rs file and are compiled as unit tests - usually they would be located in tests/, however, that would require separation of the built binary to wrap a library which wouldn't fit the scope of this much smaller program right. The integration tests cover processing of transactions, not CSV parsing as that is tested within the 3rd party library which I have used.

About


Languages

Language:Rust 100.0%