Last active
July 1, 2020 21:18
-
-
Save virattt/ed527240ee08baa57b10b79410ff43bc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.libjava; | |
import com.example.libjava.models.Response; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Set; | |
import io.reactivex.rxjava3.annotations.NonNull; | |
import io.reactivex.rxjava3.core.Observable; | |
import io.reactivex.rxjava3.core.ObservableEmitter; | |
import io.reactivex.rxjava3.core.ObservableOnSubscribe; | |
import io.reactivex.rxjava3.functions.Consumer; | |
import io.reactivex.rxjava3.schedulers.Schedulers; | |
public class AirtableApi { | |
/** | |
* Requirements: | |
* 1. To make the API call, given a 'key' | |
* 2. Has mechanism (shouldMakeBatchAPICall()), which is dependent on time (time of first request vs. time of current request) | |
* 3. createBatchAPICall(...) | |
* 4. return appropriate response to the correct caller | |
* | |
* Order of operations: | |
* - Prevent rapid network calls (if client tries to do this, then batch all requests) | |
* - | |
* | |
* Thoughts: | |
* - keys: | |
* => Only add keys for a given batch | |
* => Once batch request is successfully executed, then clear the keys | |
* | |
*/ | |
private final long WINDOW_MS = 1000; | |
private long previousBatchRequestMs = 0; | |
private Set<String> batch; | |
private Map<String, List<Listener>> listenerMap; | |
public AirtableApi() { | |
} | |
public void executeAPICall(String key, Listener listener) { | |
if (shouldCreateNewBatch(System.currentTimeMillis())) { | |
// Create new batch | |
batch = createBatch(key); | |
listenerMap = createListenerMap(key, listener); | |
} else { | |
// Add to existing batch | |
addToBatch(key); | |
addToListenerMap(key, listener); | |
} | |
makeAPICall(batch, listener); | |
} | |
private void makeAPICall(Set<String> batch, listener) { | |
Observable<Response> networkRequest = createNetworkRequest(batch); | |
networkRequest | |
.subscribeOn(Schedulers.io()) | |
.observeOn(Schedulers.single()) | |
.subscribe(new Consumer<Response>() { | |
@Override | |
public void accept(Response response) throws Throwable { | |
// Return this response to callers | |
for (String key : listenerMap.keys()) { | |
List<Listener> listeners = listenerMap.get(key); | |
for (Listener listener : listeners) { | |
listener.onResponse(response.getResponseForKey(key)); | |
} | |
} | |
} | |
}); | |
} | |
private Observable<Response> createNetworkRequest(final Set<String> batch) { | |
return Observable.create(new ObservableOnSubscribe<Response>() { | |
@Override | |
public void subscribe(@NonNull ObservableEmitter<Response> emitter) throws Throwable { | |
try { | |
// Make API call | |
Response response = apiCall(batch); | |
emitter.onNext(response); | |
emitter.onComplete(); | |
} catch (Exception e) { | |
emitter.onError(e); | |
} | |
} | |
}); | |
} | |
private Response apiCall(Set<String> batch) { | |
return new Response(); | |
} | |
private boolean shouldCreateNewBatch(long currentTimeMillis) { | |
if (currentTimeMillis - previousBatchRequestMs > WINDOW_MS) { | |
previousBatchRequestMs = currentTimeMillis; | |
return true; | |
} | |
return false; | |
} | |
private Set<String> createBatch(String key) { | |
batch = new HashSet<>(); | |
batch.add(key); | |
return batch; | |
} | |
private Map<String, List<Listener>> createListenerMap(String key, Listener listener) { | |
listenerMap = new HashMap<String, List<Listener>>(); | |
listenerMap.put(key, new ArrayList<>(listener)); | |
return listenerMap; | |
} | |
private String addToBatch(String key) { | |
batch.add(key); | |
return key; | |
} | |
private String addToBatch(String key, Listener listener) { | |
List<Listener> listeners = listenerMap.getOrDefault(key, new ArrayList<>()); | |
listeners.add(listener); | |
listenerMap.put(key, listeners) | |
return key; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.libjava.models; | |
public class Response { | |
public Response() { | |
} | |
/** | |
* { | |
* "foo": 12, | |
* "bar": 42 | |
* } | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment