io.keen.client.java.FileEventStore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of keen-client-java-core Show documentation
Show all versions of keen-client-java-core Show documentation
Java Client Core Library for Keen
package io.keen.client.java;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* Implementation of the {@link io.keen.client.java.KeenEventStore} interface using the file system
* to cache events in between queueing and batch posting.
*
* @author Kevin Litwack ([email protected])
* @since 2.0.0
*/
public class FileEventStore implements KeenEventStore {
///// PUBLIC CONSTRUCTORS /////
/**
* Constructs a new File-based event store.
*
* @param root The root directory in which to store queued event files.
* @throws IOException If the provided {@code root} isn't an existing directory.
*/
public FileEventStore(File root) throws IOException {
if (!root.exists() || !root.isDirectory()) {
throw new IOException("Event store root '" + root + "' must exist and be a directory");
}
this.root = root;
}
///// PUBLIC METHODS /////
/**
* {@inheritDoc}
*/
@Override
public Object store(String projectId, String eventCollection,
String event) throws IOException {
// Prepare the collection cache directory.
File collectionCacheDir = prepareCollectionDir(projectId, eventCollection);
// Create the cache file.
Calendar timestamp = Calendar.getInstance();
File cacheFile = getFileForEvent(collectionCacheDir, timestamp);
// Write the event to the cache file.
Writer writer = null;
try {
OutputStream out = new FileOutputStream(cacheFile);
writer = new OutputStreamWriter(out, ENCODING);
writer.write(event);
} finally {
KeenUtils.closeQuietly(writer);
}
// Return the file as the handle to use for retrieving/removing the event.
return cacheFile;
}
/**
* {@inheritDoc}
*/
@Override
public String get(Object handle) throws IOException {
if (!(handle instanceof File)) {
throw new IllegalArgumentException("Expected File, but was " + handle.getClass());
}
File eventFile = (File) handle;
if (eventFile.exists() && eventFile.isFile()) {
return KeenUtils.convertFileToString(eventFile);
} else {
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public void remove(Object handle) throws IOException {
if (!(handle instanceof File)) {
throw new IllegalArgumentException("Expected File, but was " + handle.getClass());
}
File eventFile = (File) handle;
if (eventFile.exists() && eventFile.isFile()) {
if (eventFile.delete()) {
KeenLogging.log(String.format(Locale.US, "Successfully deleted file: %s",
eventFile.getAbsolutePath()));
} else {
KeenLogging.log(String.format(Locale.US,
"CRITICAL ERROR: Could not remove event at %s",
eventFile.getAbsolutePath()));
}
} else {
KeenLogging.log(String.format(Locale.US, "WARNING: no event found at %s",
eventFile.getAbsolutePath()));
}
}
/**
* {@inheritDoc}
*/
@Override
public Map> getHandles(String projectId) throws IOException {
File projectDir = getProjectDir(projectId, false);
if (projectDir.exists() && projectDir.isDirectory()) {
return getHandlesFromProjectDirectory(projectDir);
} else {
return new HashMap>();
}
}
///// PRIVATE CONSTANTS /////
/**
* The encoding to use when writing events to files.
*/
private static final String ENCODING = "UTF-8";
/**
* The number of events that can be stored for a single collection before aging them out.
*/
private static final int MAX_EVENTS_PER_COLLECTION = 10000;
/**
* The number of events to drop when aging out.
*/
private static final int NUMBER_EVENTS_TO_FORGET = 100;
///// PRIVATE FIELDS /////
private final File root;
///// PRIVATE METHODS /////
/**
* Gets the handle map for all collections in the specified project cache directory.
*
* @param projectDir The cache directory for the project.
* @return The handle map. See {@link #getHandles(String)} for details.
* @throws IOException If there is an error reading the event files.
*/
private Map> getHandlesFromProjectDirectory(File projectDir) throws
IOException {
File[] collectionDirs = getSubDirectories(projectDir);
Map> handleMap = new HashMap>();
if (collectionDirs != null) {
// iterate through the directories
for (File directory : collectionDirs) {
String collectionName = directory.getName();
File[] files = getFilesInDir(directory);
if (files != null) {
List