Skip to content
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

Adding retry feature to mobile apiFetch handler #1686

Merged
merged 8 commits into from
Jan 31, 2020
3 changes: 2 additions & 1 deletion android/app/src/main/java/com/gutenberg/MainApplication.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.gutenberg;

import android.app.Application;
import android.os.Bundle;
import android.util.Log;

import androidx.core.util.Consumer;
Expand Down Expand Up @@ -118,7 +119,7 @@ public void editorDidEmitLog(String message, LogLevel logLevel) {
}

@Override
public void performRequest(String path, Consumer<String> onSuccess, Consumer<String> onError) {}
public void performRequest(String path, Consumer<String> onSuccess, Consumer<Bundle> onError) {}
});

return new ReactNativeHost(this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import androidx.annotation.Nullable;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
Expand Down Expand Up @@ -197,7 +198,15 @@ public void getOtherMediaOptions(ReadableArray filter, final Callback jsCallback
public void fetchRequest(String path, Promise promise) {
mGutenbergBridgeJS2Parent.performRequest(path,
promise::resolve,
errorMessage -> promise.reject(new Error(errorMessage)));
errorBundle -> {
WritableMap writableMap = Arguments.makeNativeMap(errorBundle);
if (writableMap.hasKey("code")) {
String code = String.valueOf(writableMap.getInt("code"));
promise.reject(code, new Error(), writableMap);
} else {
promise.reject(new Error(), writableMap);
}
});
}

private OtherMediaOptionsReceivedCallback getNewOtherMediaReceivedCallback(final Callback jsCallback) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.wordpress.mobile.WPAndroidGlue;

import android.os.Bundle;

import androidx.core.util.Consumer;

public interface RequestExecutor {
void performRequest(String path, Consumer<String> onSuccess, Consumer<String> onError);
void performRequest(String path, Consumer<String> onSuccess, Consumer<Bundle> onError);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import com.facebook.react.ReactInstanceManagerBuilder;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.LifecycleState;
Expand Down Expand Up @@ -302,7 +301,7 @@ public void requestMediaPickFrom(String mediaSource,
}

@Override
public void performRequest(String pathFromJS, Consumer<String> onSuccess, Consumer<String> onError) {
public void performRequest(String pathFromJS, Consumer<String> onSuccess, Consumer<Bundle> onError) {
mRequestExecutor.performRequest(pathFromJS, onSuccess, onError);
}

Expand Down
15 changes: 12 additions & 3 deletions src/api-fetch-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { fetchRequest } from 'react-native-gutenberg-bridge';
*/
import apiFetch from '@wordpress/api-fetch';

const fetchHandler = ( { path } ) => {
const setTimeoutPromise = ( delay ) => new Promise( ( resolve ) => setTimeout( resolve, delay ) );

const fetchHandler = ( { path }, retries = 20, retryCount = 1 ) => {
if ( ! isPathSupported( path ) ) {
return Promise.reject( `Unsupported path: ${ path }` );
}
Expand All @@ -26,8 +28,15 @@ const fetchHandler = ( { path } ) => {

return responsePromise.then( parseResponse ).catch( ( error ) => {
// eslint-disable-next-line no-console
console.warn( 'Network Error: ', error );
return Promise.resolve( error );
console.warn( 'Network Error: ', JSON.stringify( error, null, 2 ) );
if ( error.code >= 400 && error.code < 600 ) {
return error;
} else if ( retries === 0 ) {
return Promise.reject( error );
}
return setTimeoutPromise( 1000 * retryCount ).then( () =>
fetchHandler( { path }, retries - 1, retryCount + 1 )
);
} );
};

Expand Down