Skip to content

Instantly share code, notes, and snippets.

@mgp
Created January 25, 2016 06:52
Show Gist options
  • Save mgp/f9dcd8fd3850d97e88b1 to your computer and use it in GitHub Desktop.
Save mgp/f9dcd8fd3850d97e88b1 to your computer and use it in GitHub Desktop.
package org.khanacademy.core.net;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.khanacademy.core.exceptions.BaseRuntimeException;
import org.khanacademy.core.logging.KALogger;
import com.google.common.base.Optional;
import com.squareup.okhttp.Cache;
import com.squareup.okhttp.OkHttpClient;
import java.io.File;
/**
* An {@link OkHttpClient} that is configured to cache data of a specified type.
*
* This allows each data type to have a dedicated cache with a maximum size that is proportional to
* the size of that data. Unlike with a shared cache, caching an large resource belonging to one
* data type will not evict multiple small resources belonging to another data type. Consequently
* the caching policy is more fair.
*/
public final class CachingOkHttpClient {
public enum CachedDataType {
DEFAULT(10 * 1024 * 1024),
VIDEO(25 * 1024 * 1024);
// How many bytes of this data type should be cached.
private final int cacheSizeBytes;
CachedDataType(int cacheSizeBytes) {
checkArgument(cacheSizeBytes >= 0, "Invalid cacheSizeBytes: " + cacheSizeBytes);
this.cacheSizeBytes = cacheSizeBytes;
}
}
private final OkHttpClient mDefaultClient;
private final OkHttpClient mVideoClient;
/**
* Returns a {@link CachingOkHttpClient} for the given {@link OkHttpClient} that has no
* configured cache.
*
* If parameter {@code defaultCacheDir} is present, then the {@link OkHttpClient} for
* data type {@link CachedDataType#DEFAULT} will cache data in the specified directory.
*
* If parameter {@code videoCacheDir} is present, then the {@link OkHttpClient} for
* data type {@link CachedDataType#VIDEO} will cache data in the specified directory.
*/
public static CachingOkHttpClient create(final OkHttpClient baseClient,
final Optional<File> defaultCacheDir,
final Optional<File> videoCacheDir,
final KALogger.Factory loggerFactory) {
checkNotNull(baseClient);
checkArgument(baseClient.getCache() == null,
"OkHttpClient already has a cache: " + baseClient.getCache());
checkNotNull(defaultCacheDir);
checkNotNull(videoCacheDir);
checkNotNull(loggerFactory);
final OkHttpClient defaultClient = applyCachingConfiguration(
baseClient, defaultCacheDir, CachedDataType.DEFAULT, loggerFactory
);
final OkHttpClient videoClient = applyCachingConfiguration(
baseClient, videoCacheDir, CachedDataType.VIDEO, loggerFactory
);
return new CachingOkHttpClient(defaultClient, videoClient);
}
private static OkHttpClient applyCachingConfiguration(final OkHttpClient baseClient,
final Optional<File> cacheDirOptional,
final CachedDataType dataType,
final KALogger.Factory loggerFactory) {
if (cacheDirOptional.isPresent()) {
// Return an OkHttpClient that caches data in the given directory.
final File cacheDir = cacheDirOptional.get();
final OkHttpClient cachingClient = baseClient.clone();
cachingClient.setCache(new Cache(cacheDir, dataType.cacheSizeBytes));
return cachingClient;
} else {
// No directory specified, so do not cache data of this type.
final KALogger logger = loggerFactory.createForTagClass(CachingOkHttpClient.class);
logger.nonFatalFailure(
new BaseRuntimeException("Could not create cache directory for data type "
+ dataType)
);
return baseClient;
}
}
private CachingOkHttpClient(final OkHttpClient defaultClient, final OkHttpClient videoClient) {
mDefaultClient = checkNotNull(defaultClient);
mVideoClient = checkNotNull(videoClient);
}
/**
* @return the {@link OkHttpClient} that is configured to cache data of the given type
*/
public OkHttpClient getClient(CachedDataType dataType) {
checkNotNull(dataType);
switch (dataType) {
case DEFAULT:
return mDefaultClient;
case VIDEO:
return mVideoClient;
default:
break;
}
throw new IllegalArgumentException("Invalid data type: " + dataType);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment