package org.limewire.promotion;
import java.util.Set;
import org.limewire.promotion.impressions.ImpressionsCollector;
import org.limewire.promotion.impressions.UserQueryEvent;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class PromotionBinderRepositoryImpl implements PromotionBinderRepository {
private final PromotionBinderRequestor requestor;
private final ImpressionsCollector impressionsCollector;
private final SearcherDatabase searcherDatabase;
private final PromotionServices promotionServices;
/** The search URL. */
private String searchUrl;
/** The modulus to take with the bucket ID. */
private int modulus;
@Inject
public PromotionBinderRepositoryImpl(final PromotionBinderRequestor requestor,
final ImpressionsCollector impressionsCollector, final SearcherDatabase searcherDatabase, PromotionServices promotionServices) {
this.requestor = requestor;
this.impressionsCollector = impressionsCollector;
this.searcherDatabase = searcherDatabase;
this.promotionServices = promotionServices;
}
public PromotionBinder getBinderForBucket(final long bucketNumber) {
// See if we have a cached binder...
final int bucket = (int) (bucketNumber % modulus);
try {
searcherDatabase.expungeExpired();
} catch (DatabaseExecutionException e) {
promotionServices.stop();
return null;
}
final PromotionBinder binder = searcherDatabase.getBinder(bucket);
if (binder != null)
return binder;
else
return getBinderForBucketOnNetwork(bucket);
}
public void init(final String url, final int modulus) {
this.searchUrl = url;
this.modulus = modulus;
}
/**
* Queries the network for the given bucket.
*
* @param bucketNumber the bucket number (modulus'ed down from the 63-bit
* monster)
* @param callback where to drop the binder after retrieval
*/
private PromotionBinder getBinderForBucketOnNetwork(final long bucketNumber) {
final Set<UserQueryEvent> queries = impressionsCollector.getCollectedImpressions();
String url = searchUrl;
url += "?now=" + System.currentTimeMillis() / 1000;
PromotionBinder result = requestor.request(url, bucketNumber, queries);
//TODO: if there was an exception contacting the server, the impressions
// aren't really recorded, but this still erases them.
// Now remove the query events
impressionsCollector.removeImpressions(queries);
return result;
}
}