Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save shoaibi/6ca17e757af88ea13580 to your computer and use it in GitHub Desktop.
Save shoaibi/6ca17e757af88ea13580 to your computer and use it in GitHub Desktop.
My proposal of how to architect the Currency Fair Trends challenge
Framework of choice: yii2.
Configure application log to log all exceptions.
Configure FileCache(just to have something to later replace, say, by Redis)
2 apps using same configs, same code: frontend, api.
Api application would have a module called v1.
Url pattern: http://app.com/ , http://api.app.com/v1/tradeMessages/consume
Trends:
- Most active user
- Most Active originating country
- Most popular from currency
- Most popular to currency
- Busiest Day of Month
- Busiest Hour of Day
- Largest amount Sold
- Largest amount bought
OOP Structure:
- abstract class BaseTrend
- one abstract methods:
-- getTrendValue(Database $db)
- non abstract methods:
-- getCacheKey: returns get_class($this);
-- getUserFriendlyName: returns class name by adding a space before every upper case letter.
- All trends classes(say MostActiveUserTrend) extend BaseTrend and override the methods, say MostActiveUserTrend overrides getTrendValue and uses passed in Database object to query the user_id that occurs the most in tradeMessages.
- abstract Trends class:
-- static getSupportedTrendClassNames() // returns an array of class names of supported trends.
-- static getSupportedTrends(), returns an array with objects of each supported trend.
Api App, v1 module:
- v1 module would have a controller: tradeMessages and an action: consume.
- This action would only accept POST requests.
- Would use basic or OAuth using behaviors provided by yii2
- Would use RateLimiter behavior to pose 2 limitations:
-- X req/minute (Mostly for fair use, application wide setting)
-- X req/day (User Quota, say bounding it to a user's paid plan/package)
- Action does following:
-- Gets the POST request
-- Ensures it contains JSON and only JSON, else HTTP400.
-- Decodes JSON, on error HTTP400
-- Assign decoded array to TradeMessage Model
-- Run TradeMessage->valid(), if fails: HTTP 400
-- If data is valid, add a new record, log it.
frontend app, Index Controller, Index Action.
- A bootstrap Hero well showing Trends
- A bootstrap table with sort and filter functionality to show all messages
- May be a JS function that runs every X+5 seconds(where X is the interval at which RefreshTrendsCacheCommand runs) to query renderTrends action and update the trends div.
frontend app, Index Controller, renderTrends Action:
- renderPartial()
- use a view to dump trends values from cache.
TradeMessage Model:
- Strict Validation rules:
-- userId: Integer, min: 1, must exist in User Model.
-- currencyFrom: character, length=3, must be all caps.
-- currencyTo: character, length=3, must be all caps.
-- amountSell: Integer, min: 100(business logic), max: 10000 (business logic)
-- amountBuy: Float, 2 degrees of precision, min: 50(business logic), max: 10000 (business logic)
-- rate: Float, 4 degrees of precision, min: 0.1 (business logic)
-- timePlaced: string, length = 18, yii date validator with custom format, must be in future of now-1h ago.
-- originatingCountry: character, length =2, must be all caps.
Depends on Business logic we could further restrict validation of currencyFrom, currencyTo and originatingCountry to an array(extracted from db, webservice) of supported values.
- Override save() to use "insert delayed" instead of "insert"
Because we use "insert delayed" in save() here, we can't use the afterSave() (which wouldn't fire in this case) to fire the trendCache.overwrite event.
RefreshTrendsCacheCommand:
- Yii2 app command to fire trendCache.overwrite event
- Coupled with a cron to be fired at specific intervals.
trendCache.overwrite event handler:
- $supportedTrends = Trends::getSupportedTrends();
- For each supported trend: call getCacheKey() and getTrendValue(), overwrite the value in cache
User Model:
- Used for binding TradeMessage to specific users
- Used to enforce rate limitter
- Used for authentication on api actions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment