Skip to content

Commit

Permalink
Separate restoring saga
Browse files Browse the repository at this point in the history
  • Loading branch information
kuy committed Jun 15, 2016
1 parent 1c55945 commit 9388aec
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 18 deletions.
4 changes: 3 additions & 1 deletion reject/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export const CHANGE_BEHAVIOR = 'CHANGE_BEHAVIOR';
export const changeBehavior = createAction(CHANGE_BEHAVIOR);

export const CHANGE_SUBJECT = 'CHANGE_SUBJECT';
export const changeSubject = createAction(CHANGE_SUBJECT);
const changeSubject = createAction(CHANGE_SUBJECT);
changeSubject.fromSaga = createAction(CHANGE_SUBJECT, a => a, () => ({ source: 'saga' }));
export { changeSubject };

export const REQUEST_UPDATE_SUBJECT = 'REQUEST_UPDATE_SUBJECT';
export const SUCCESS_UPDATE_SUBJECT = 'SUCCESS_UPDATE_SUBJECT';
Expand Down
4 changes: 2 additions & 2 deletions reject/app.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Text from 'react-edit-inline';
import { requestUpdateSubject, changeBehavior } from './actions';
import { changeSubject, changeBehavior } from './actions';

class App extends Component {
handleSubject({ subject }) {
this.props.dispatch(requestUpdateSubject({ subject }));
this.props.dispatch(changeSubject(subject));
}

handleBehavior(e) {
Expand Down
44 changes: 29 additions & 15 deletions reject/sagas.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { takeEvery } from 'redux-saga';
import { call, put, fork, select } from 'redux-saga/effects';
import { call, put, fork, select, take } from 'redux-saga/effects';
import {
REQUEST_UPDATE_SUBJECT, changeSubject, successUpdateSubject, failureUpdateSubject
CHANGE_SUBJECT, SUCCESS_UPDATE_SUBJECT, FAILURE_UPDATE_SUBJECT,
changeSubject, successUpdateSubject, failureUpdateSubject, requestUpdateSubject
} from './actions';

function result(behavior) {
Expand Down Expand Up @@ -29,33 +30,46 @@ function updateSubject(subject, behavior) {
.catch(error => ({ error }));
}

function* runUpdateSubject({ payload }) {
// Backup current subject as prev subject for restoring later if needed
const { subject: prevSubject } = yield select(state => state.post);
function* runUpdateSubject({ payload: newSubject, meta }) {
// Ignore changes from Sagas
if (meta && meta.source === 'saga') {
return;
}

// Change to new subject immediately for UX
const newSubject = payload.subject;
yield put(changeSubject(newSubject));
// Notify we're about to start a request
yield put(requestUpdateSubject());

const { behavior } = yield select(state => state.app);
const { data, error } = yield call(updateSubject, newSubject, behavior);
if (data && !error) {
yield put(successUpdateSubject({ data }));

// Nothing to do here, because new subject is already set
} else {
yield put(failureUpdateSubject({ error }));

// Rollback to previous subject
console.log('rollback', prevSubject);
yield put(changeSubject(prevSubject));
}
}

function* handleUpdateSubject() {
yield* takeEvery(REQUEST_UPDATE_SUBJECT, runUpdateSubject);
yield* takeEvery(CHANGE_SUBJECT, runUpdateSubject);
}

function* restoreSubject() {
// Backup initial subject
let prevSubject = yield select(state => state.post.subject);

while (true) {
// Detect success or failure
const { type, payload } = yield take([SUCCESS_UPDATE_SUBJECT, FAILURE_UPDATE_SUBJECT]);
if (type === SUCCESS_UPDATE_SUBJECT) {
// Store new subject for next rollback
prevSubject = yield select(state => state.post.subject);
} else {
// Rollback!
yield put(changeSubject.fromSaga(prevSubject));
}
}
}

export default function* rootSaga() {
yield fork(restoreSubject);
yield fork(handleUpdateSubject);
}

0 comments on commit 9388aec

Please sign in to comment.