Skip to content

Commit

Permalink
Merge pull request #3418 from Vizzuality/feature/request-cache
Browse files Browse the repository at this point in the history
Feature/request cache
  • Loading branch information
edbrett committed May 21, 2018
2 parents 7ee7361 + 79ec245 commit b020c0f
Show file tree
Hide file tree
Showing 32 changed files with 346 additions and 93 deletions.
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:
```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

0 comments on commit b020c0f

Please sign in to comment.