Created
January 25, 2016 06:52
-
-
Save mgp/f9dcd8fd3850d97e88b1 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 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