Skip to content

Feature/request cache #3418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
May 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ gem 'rmagick', :require => false
gem 'mini_magick'
gem 'unf'
gem 'sitemap_generator'
gem 'redis'
gem 'redis-namespace'
gem 'redis-rails'

# requirejs
gem 'erubis'
Expand Down
22 changes: 22 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,25 @@ GEM
json (>= 1.8)
nokogiri (~> 1.5)
trollop (~> 2.1)
redis (4.0.1)
redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6)
redis-rack (>= 1, < 3)
redis-store (>= 1.1.0, < 2)
redis-activesupport (5.0.4)
activesupport (>= 3, < 6)
redis-store (>= 1.3, < 2)
redis-namespace (1.6.0)
redis (>= 3.0.4)
redis-rack (2.0.4)
rack (>= 1.5, < 3)
redis-store (>= 1.2, < 2)
redis-rails (5.0.2)
redis-actionpack (>= 5.0, < 6)
redis-activesupport (>= 5.0, < 6)
redis-store (>= 1.2, < 2)
redis-store (1.5.0)
redis (>= 2.2, < 5)
requirejs-rails (1.0.0)
railties (>= 3.1.1)
responders (2.4.0)
Expand Down Expand Up @@ -489,6 +508,9 @@ DEPENDENCIES
rails (= 5.1.5)
rails-controller-testing
rails_12factor
redis
redis-namespace
redis-rails
requirejs-rails (= 1.0.0)
responders (~> 2.0)
rmagick
Expand Down
1 change: 1 addition & 0 deletions Procfile.dev
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
web: bundle exec rails s
web: redis-server /usr/local/etc/redis.conf
# watcher: ./bin/webpack-watcher
webpacker: ./bin/webpack-dev-server
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ $ rvm install 2.4.0
$ rvm use 2.4.0
```

Now let's install redis:
```bash
$ brew install redis
```

Now let's install Ruby on Rails:

```bash
Expand Down Expand Up @@ -95,6 +100,13 @@ We follow a [Gitflow Worklow](https://www.atlassian.com/git/tutorials/comparing-

![gitflow workflow](https://www.atlassian.com/dam/jcr:b5259cce-6245-49f2-b89b-9871f9ee3fa4/03%20(2).svg)

#### Clear Redis cache
If you need to clear the Redis cache after deploy, run these commands on your local terminal:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we automate this to happen on build? So when we deploy the cache is flushed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will not be possible 😭 😭 I've spent almost the whole day yesterday, trying to find a solution, but Heroku is a very hard bastard. I wanted to talk to someone expert in Heroku to see if he could come up with any solution.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that is very annoying. maybe @simaob can help?

```bash
$ heroku redis:cli -a MY_APP_ID --confirm MY_APP_ID
$ flushall
```

## Releases

We are using github releases to record changes to the app. To help us manage this we are using [Zeit Releases](https://github.com/zeit/release), an npm package for handling github releases, tagging commits (major, minor, patch), and automating semantic release logs. For a more detailed explantion of semantic changelogs see [this post](https://semver.org/).
Expand Down
27 changes: 27 additions & 0 deletions app/controllers/cache_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class CacheController < ApplicationController
skip_before_action :verify_authenticity_token

def index
data = $redis.get(params[:id])
if data
data = JSON.parse(data)
end

render :json => data
end

def add
id = params[:id]
data = params[:data].to_json
expire = params[:expire] || 86400
$redis.set(id, data, ex: expire)

render :json => { id: id, data: data, expire: expire }
end

def keys
data = $redis.keys('*')
render :json => { data: data }
end

end
13 changes: 9 additions & 4 deletions app/javascript/components/map/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ class MapContainer extends PureComponent {
}

componentDidMount() {
const { mapOptions, getLayerSpec, setMapSettings } = this.props;
const { mapOptions, setMapSettings } = this.props;
this.buildMap();
getLayerSpec();
setMapSettings(mapOptions);
}

Expand All @@ -57,9 +56,15 @@ class MapContainer extends PureComponent {
bounds,
layersKeys,
settings,
options
options,
getLayerSpec
} = nextProps;
if (isParentLoading !== this.props.isParentLoading && bounds) {
const parentLoadingChanged = isParentLoading !== this.props.isParentLoading;

if (parentLoadingChanged) {
getLayerSpec();
}
if (parentLoadingChanged && bounds) {
this.boundMap(nextProps.bounds);
this.setAreaHighlight();
this.updateLayers(layersKeys, this.props.layersKeys, settings);
Expand Down
7 changes: 7 additions & 0 deletions app/javascript/data/cache-exceptions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"id": "gladRequest",
"type": "excludeWeekDay",
"data": [4, 5]
}
]
24 changes: 12 additions & 12 deletions app/javascript/pages/country/header/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,20 @@ const mapDispatchToProps = (dispatch, ownProps) => {
};

class HeaderContainer extends PureComponent {
componentDidMount() {
const { location, settings, getHeaderData } = this.props;
getHeaderData({ ...location, ...settings });
if (location.region) {
getHeaderData({ ...location, ...settings });
}
if (location.subRegion) {
getHeaderData({ ...location, ...settings });
}
}

componentWillReceiveProps(nextProps) {
const { location, settings } = nextProps;
const { location, isParentLoading, settings } = nextProps;
const { getHeaderData } = this.props;

if (isParentLoading !== this.props.isParentLoading) {
getHeaderData({ ...location, ...settings });
if (location.region) {
getHeaderData({ ...location, ...settings });
}
if (location.subRegion) {
getHeaderData({ ...location, ...settings });
}
}

if (!isEqual(location, this.props.location)) {
getHeaderData({ ...nextProps.location, ...settings });
}
Expand Down Expand Up @@ -171,6 +170,7 @@ class HeaderContainer extends PureComponent {

HeaderContainer.propTypes = {
location: PropTypes.object.isRequired,
isParentLoading: PropTypes.bool.isRequired,
locationNames: PropTypes.object.isRequired,
getHeaderData: PropTypes.func.isRequired,
data: PropTypes.object.isRequired,
Expand Down
4 changes: 3 additions & 1 deletion app/javascript/pages/country/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { handleActionTrack } from 'utils/analytics';
import { cacheMiddleware } from 'utils/request';

import 'react-tippy/dist/tippy.css';
import 'styles/styles.scss';
Expand All @@ -18,7 +19,8 @@ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const middlewares = applyMiddleware(
thunk,
router.middleware,
handleActionTrack
handleActionTrack,
cacheMiddleware
);
const store = createStore(
reducers,
Expand Down
11 changes: 8 additions & 3 deletions app/javascript/pages/country/page/page-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import Sticky from 'react-stickynode';
import { SCREEN_M, SCREEN_MOBILE } from 'utils/constants';

import CacheProvider from 'providers/cache-provider';
import CountryDataProvider from 'providers/country-data-provider';
import WhitelistsProvider from 'providers/whitelists-provider';

Expand All @@ -28,6 +29,7 @@ class Page extends PureComponent {
showMapMobile,
setShowMapMobile,
links,
isCacheListLoading,
isGeostoreLoading,
location,
locationOptions,
Expand Down Expand Up @@ -56,6 +58,7 @@ class Page extends PureComponent {
location={location}
locationOptions={locationOptions}
locationNames={locationNames}
isParentLoading={isCacheListLoading}
/>
<SubNavMenu
className="nav"
Expand Down Expand Up @@ -90,7 +93,7 @@ class Page extends PureComponent {
zoom: 8
}}
areaHighlight={locationGeoJson}
isParentLoading={isGeostoreLoading}
isParentLoading={isCacheListLoading || isGeostoreLoading}
widgetKey={activeWidget}
/>
</div>
Expand All @@ -110,8 +113,9 @@ class Page extends PureComponent {
<Share />
<ModalMeta />
{widgetAnchor && <ScrollTo target={widgetAnchor} />}
<CountryDataProvider />
<WhitelistsProvider />
<CacheProvider />
<CountryDataProvider isParentLoading={isCacheListLoading} />
<WhitelistsProvider isParentLoading={isCacheListLoading} />
<Meta
page={
locationNames &&
Expand All @@ -128,6 +132,7 @@ Page.propTypes = {
showMapMobile: PropTypes.bool.isRequired,
setShowMapMobile: PropTypes.func.isRequired,
links: PropTypes.array.isRequired,
isCacheListLoading: PropTypes.bool,
isGeostoreLoading: PropTypes.bool,
location: PropTypes.object,
locationOptions: PropTypes.object,
Expand Down
3 changes: 2 additions & 1 deletion app/javascript/pages/country/page/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Component from './page-component';

const actions = { ...mapActions };

const mapStateToProps = ({ countryData, whitelists, location, map }) => {
const mapStateToProps = ({ cache, countryData, whitelists, location, map }) => {
const category = (location.query && location.query.category) || 'summary';
const {
countryWhitelistLoading,
Expand Down Expand Up @@ -44,6 +44,7 @@ const mapStateToProps = ({ countryData, whitelists, location, map }) => {
return {
showMapMobile: map.showMapMobile,
links: getLinks({ categories: CATEGORIES, ...location, category }),
isCacheListLoading: cache.cacheListLoading,
isGeostoreLoading: countryData.isGeostoreLoading,
category,
widgets,
Expand Down
2 changes: 2 additions & 0 deletions app/javascript/pages/country/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as HeaderComponent from 'pages/country/header';
import * as WidgetsComponent from 'components/widgets';

// Providers
import * as cacheProviderComponent from 'providers/cache-provider';
import * as countryDataProviderComponent from 'providers/country-data-provider';
import * as whitelistsProviderComponent from 'providers/whitelists-provider';

Expand All @@ -27,6 +28,7 @@ const componentsReducers = {

// Provider Reducers
const providersReducers = {
cache: handleActions(cacheProviderComponent),
countryData: handleActions(countryDataProviderComponent),
whitelists: handleActions(whitelistsProviderComponent)
};
Expand Down
25 changes: 25 additions & 0 deletions app/javascript/providers/cache-provider/cache-provider-actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createAction } from 'redux-actions';
import { createThunkAction } from 'utils/redux';

import { getKeys } from 'services/cache';

export const setCacheList = createAction('setCacheList');
export const setCacheError = createAction('setCacheError');

export const getCacheList = createThunkAction(
'getCacheList',
() => dispatch => {
getKeys()
.then(response => {
if (response.data.data) {
dispatch(setCacheList(response.data.data));
} else {
dispatch(setCacheError(true));
}
})
.catch(error => {
dispatch(setCacheError(true));
console.info(error);
});
}
);
22 changes: 22 additions & 0 deletions app/javascript/providers/cache-provider/cache-provider-reducers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export const initialState = {
cacheListLoading: true,
cacheList: [],
error: false
};

const setCacheList = (state, { payload }) => ({
...state,
cacheListLoading: false,
cacheList: payload
});

const setCacheError = (state, { payload }) => ({
...state,
cacheListLoading: false,
error: payload
});

export default {
setCacheList,
setCacheError
};
24 changes: 24 additions & 0 deletions app/javascript/providers/cache-provider/cache-provider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { PureComponent } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import * as actions from './cache-provider-actions';
import reducers, { initialState } from './cache-provider-reducers';

class CacheProvider extends PureComponent {
componentWillMount() {
const { getCacheList } = this.props;
getCacheList();
}

render() {
return null;
}
}

CacheProvider.propTypes = {
getCacheList: PropTypes.func.isRequired
};

export { actions, reducers, initialState };
export default connect(null, actions)(CacheProvider);
Loading