Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[15x] Remove "Future queries" findFutureList, findFutureIds, findFutureCount" #3340

Merged
merged 2 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions ebean-api/src/main/java/io/ebean/ExpressionList.java
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,42 @@ default <A> A findSingleAttribute() {
*/
Optional<T> findOneOrEmpty();

/**
* Execute find row count query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @return a Future object for the row count query
*/
FutureRowCount<T> findFutureCount();

/**
* Execute find Id's query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @return a Future object for the list of Id's
*/
FutureIds<T> findFutureIds();

/**
* Execute find list query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @return a Future object for the list result of the query
*/
FutureList<T> findFutureList();

/**
* Return a PagedList for this query using firstRow and maxRows.
* <p>
Expand Down
20 changes: 20 additions & 0 deletions ebean-api/src/main/java/io/ebean/FutureIds.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.ebean;

import java.util.List;
import java.util.concurrent.Future;

/**
* FutureIds represents the result of a background query execution for the Id's.
* <p>
* It extends the java.util.concurrent.Future with the ability to get the Id's
* while the query is still executing in the background.
* </p>
*/
public interface FutureIds<T> extends Future<List<Object>> {

/**
* Returns the original query used to fetch the Id's.
*/
Query<T> getQuery();

}
35 changes: 35 additions & 0 deletions ebean-api/src/main/java/io/ebean/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,41 @@ enum LockWait {
*/
int findCount();

/**
* Execute find row count query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @return a Future object for the row count query
*/
FutureRowCount<T> findFutureCount();

/**
* Execute find Id's query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @return a Future object for the list of Id's
*/
FutureIds<T> findFutureIds();

/**
* Execute find list query in a background thread.
* <p>
* This query will execute in it's own PersistenceContext and using its own transaction.
* What that means is that it will not share any bean instances with other queries.
* </p>
*
* @return a Future object for the list result of the query
*/
FutureList<T> findFutureList();

/**
* Return a PagedList for this query using firstRow and maxRows.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio

<T> FutureRowCount<T> findFutureCount(SpiQuery<T> query);

<T> FutureIds<T> findFutureIds(SpiQuery<T> query);

<T> FutureList<T> findFutureList(SpiQuery<T> query);

<T> PagedList<T> findPagedList(SpiQuery<T> query);

<T> Set<T> findSet(SpiQuery<T> query);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,47 @@ public <T> FutureRowCount<T> findFutureCount(SpiQuery<T> query) {
return queryFuture;
}

@Override
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
SpiQuery<T> copy = query.copy();
copy.usingFuture();
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
copy.usingTransaction(transaction);
}
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, createdTransaction));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}

@Override
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
SpiQuery<T> spiQuery = query.copy();
spiQuery.usingFuture();
// FutureList query always run in it's own persistence content
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
// Create a new transaction solely to execute the findList() at some future time
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
spiQuery.usingTransaction(transaction);
}
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, createdTransaction));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}

@Override
public <T> PagedList<T> findPagedList(SpiQuery<T> query) {
int maxRows = query.getMaxRows();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,21 @@ public int update(Transaction transaction) {
return query.update(transaction);
}

@Override
public FutureIds<T> findFutureIds() {
return query.findFutureIds();
}

@Override
public FutureRowCount<T> findFutureCount() {
return query.findFutureCount();
}

@Override
public FutureList<T> findFutureList() {
return query.findFutureList();
}

@Override
public PagedList<T> findPagedList() {
return query.findPagedList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ public ExpressionList<T> filterMany(String prop) {
return rootQuery.filterMany(prop);
}

@Override
public FutureIds<T> findFutureIds() {
return rootQuery.findFutureIds();
}

@Override
public FutureList<T> findFutureList() {
return rootQuery.findFutureList();
}

@Override
public FutureRowCount<T> findFutureCount() {
return rootQuery.findFutureCount();
}

@Override
public List<T> findList() {
return rootQuery.findList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,21 @@ public boolean exists() {
return exprList.exists();
}

@Override
public FutureIds<T> findFutureIds() {
return exprList.findFutureIds();
}

@Override
public FutureList<T> findFutureList() {
return exprList.findFutureList();
}

@Override
public FutureRowCount<T> findFutureCount() {
return exprList.findFutureCount();
}

@Override
public <A> List<A> findIds() {
return exprList.findIds();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import io.ebean.FetchConfig;
import io.ebean.FetchGroup;
import io.ebean.FetchPath;
import io.ebean.FutureIds;
import io.ebean.FutureList;
import io.ebean.FutureRowCount;
import io.ebean.OrderBy;
import io.ebean.PagedList;
import io.ebean.PersistenceContextScope;
Expand Down Expand Up @@ -348,6 +351,21 @@ public int findCount() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}

@Override
public FutureRowCount<T> findFutureCount() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}

@Override
public FutureIds<T> findFutureIds() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}

@Override
public FutureList<T> findFutureList() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}

@Override
public PagedList<T> findPagedList() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.ebeaninternal.server.query;

import io.ebean.FutureIds;
import io.ebean.Query;
import io.ebean.Transaction;

import java.util.List;
import java.util.concurrent.FutureTask;

/**
* Default implementation of FutureIds.
*/
public final class QueryFutureIds<T> extends BaseFuture<List<Object>> implements FutureIds<T> {

private final CallableQueryIds<T> call;

public QueryFutureIds(CallableQueryIds<T> call) {
super(new FutureTask<>(call));
this.call = call;
}

public FutureTask<List<Object>> futureTask() {
return futureTask;
}

public Transaction transaction() {
return call.transaction;
}

@Override
public Query<T> getQuery() {
return call.query;
}

@Override
public boolean cancel(boolean mayInterruptIfRunning) {
call.query.cancel();
return super.cancel(mayInterruptIfRunning);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package io.ebeaninternal.server.query;

import io.ebean.FutureList;
import io.ebean.Query;
import io.ebean.Transaction;

import jakarta.persistence.PersistenceException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
* Default implementation for FutureList.
*/
public final class QueryFutureList<T> extends BaseFuture<List<T>> implements FutureList<T> {

private final CallableQueryList<T> call;

public QueryFutureList(CallableQueryList<T> call) {
super(new FutureTask<>(call));
this.call = call;
}

public FutureTask<List<T>> futureTask() {
return futureTask;
}

public Transaction transaction() {
return call.transaction;
}

@Override
public Query<T> getQuery() {
return call.query;
}

@Override
public boolean cancel(boolean mayInterruptIfRunning) {
call.query.cancel();
return super.cancel(mayInterruptIfRunning);
}

@Override
public List<T> getUnchecked() {
try {
return get();

} catch (InterruptedException e) {
// restore the interrupted status (so client can check for that)
Thread.currentThread().interrupt();
throw new PersistenceException(e);

} catch (ExecutionException e) {
throw new PersistenceException(e);
}
}

@Override
public List<T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException {
try {
return get(timeout, unit);

} catch (InterruptedException e) {
// restore the interrupted status (so client can check for that)
Thread.currentThread().interrupt();
throw new PersistenceException(e);

} catch (ExecutionException e) {
throw new PersistenceException(e);
}
}

}
Loading
Loading