package org.rakam.analysis;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.rakam.analysis.metadata.QueryMetadataStore;
import org.rakam.plugin.ContinuousQuery;
import org.rakam.plugin.MaterializedView;
import org.rakam.util.AlreadyExistsException;
import org.rakam.util.MaterializedViewNotExists;
import org.rakam.util.RakamException;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.util.LongMapper;
import java.time.Clock;
import java.time.Instant;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class InMemoryQueryMetadataStore
implements QueryMetadataStore
{
private final Map<String, Set<ContinuousQuery>> continuousQueries = new HashMap<>();
private final Map<String, Set<MaterializedView>> materializedViews = new HashMap<>();
@Override
public void createMaterializedView(String project, MaterializedView materializedView)
{
Set<MaterializedView> materializedViews = this.materializedViews.computeIfAbsent(project, (key) -> new HashSet<>());
if (materializedViews.contains(materializedView)) {
throw new AlreadyExistsException("Materialized view", HttpResponseStatus.BAD_REQUEST);
}
materializedViews.add(materializedView);
}
@Override
public void deleteMaterializedView(String project, String name)
{
materializedViews.remove(getMaterializedView(project, name));
}
@Override
public MaterializedView getMaterializedView(String project, String name)
{
return materializedViews.computeIfAbsent(project, (key) -> new HashSet<>()).stream()
.filter(view -> view.tableName.equals(name))
.findAny().orElseThrow(() -> new MaterializedViewNotExists(name));
}
@Override
public List<MaterializedView> getMaterializedViews(String project)
{
return materializedViews.computeIfAbsent(project, (key) -> new HashSet<>()).stream()
.filter(view -> project.equals(project))
.collect(Collectors.toList());
}
@Override
public boolean updateMaterializedView(String project, MaterializedView userView, CompletableFuture<Instant> releaseLock)
{
MaterializedView view = materializedViews.get(project).stream()
.filter(e -> e.tableName.equals(userView.tableName)).findFirst().get();
if (!view.needsUpdate(Clock.systemUTC())) {
return false;
}
releaseLock.whenComplete((success, ex) -> {
if (success != null) {
view.lastUpdate = success;
}
});
return true;
}
@Override
public void createContinuousQuery(String project, ContinuousQuery report)
{
Set<ContinuousQuery> continuousQueries = this.continuousQueries.computeIfAbsent(project, (key) -> new HashSet<>());
if (continuousQueries.contains(report)) {
throw new AlreadyExistsException("Continuous query", HttpResponseStatus.BAD_REQUEST);
}
continuousQueries.add(report);
}
@Override
public void deleteContinuousQuery(String project, String name)
{
continuousQueries.computeIfAbsent(project, (key) -> new HashSet<>()).remove(getContinuousQuery(project, name));
}
@Override
public List<ContinuousQuery> getContinuousQueries(String project)
{
return continuousQueries.computeIfAbsent(project, (key) -> new HashSet<>()).stream()
.filter(report -> project.equals(project))
.collect(Collectors.toList());
}
@Override
public ContinuousQuery getContinuousQuery(String project, String name)
{
return continuousQueries.computeIfAbsent(project, (key) -> new HashSet<>()).stream()
.filter(view -> project.equals(project) && view.tableName.equals(name))
.findAny().get();
}
}