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

implement cancel function #1367

Merged
merged 66 commits into from
Jun 17, 2020
Merged

Conversation

Rkr1992
Copy link
Contributor

@Rkr1992 Rkr1992 commented Jun 3, 2020

Resolves #1292 (if appropriate)

Description

Motivation and Context

How Has This Been Tested?

Screenshots (if appropriate):

License

I confirm that this contribution is made under an Apache 2.0 license and that I have the authority necessary to make this contribution on behalf of its copyright owner.

* See LICENSE file in project root for terms.
*/

import org.hibernate.Session;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elide core should not depend directly on Hibernate. Only the data stores that use hibernate should have this dependency.

* Cancel Session implementation.
*/

public abstract class CancelSession {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of creating an abstract class - create a functional interface (with no dependencies on things like hibernate).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the functionalInterface will require an entityManager as an argument - and as such - it should probably live in the Aggregation Store and JpaStore respectively.

@@ -376,10 +378,10 @@ default AuditLogger getAuditLogger() {
*/
default DataStore getDataStore(MetaDataStore metaDataStore, AggregationDataStore aggregationDataStore,
EntityManagerFactory entityManagerFactory) {

CancelSession cancelSession = new CancelSession(entityManagerFactory.get().unwrap(Session.class));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YOu can make this a local variable and use it multiple places.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another issue - you are unwrapping the factory - not the entity manager. I don't think that is correct.

@@ -75,6 +83,23 @@ public void populateEntityDictionary(EntityDictionary dictionary) {

@Override
public DataStoreTransaction beginTransaction() {
return new AggregationDataStoreTransaction(queryEngine);
EntityManager entityManager = entityManagerSupplier.get();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't create an entityManager here. Let the transaction create the entity manager.


/**
* These are the classes the Aggregation Store manages.
*/
private static final List<Class<? extends Annotation>> AGGREGATION_STORE_CLASSES =
Arrays.asList(FromTable.class, FromSubquery.class);

public AggregationDataStore(QueryEngine queryEngine) {
public AggregationDataStore(EntityManagerSupplier entityManagerSupplier, QueryEngine queryEngine, AggregationDataStoreTransactionCancel aggregationDataStoreTransactionCancel) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not add an EntityManagerSupplier to the constructor.

* Functional interface for describing a method to supply EntityManager.
*/
@FunctionalInterface
public interface EntityManagerSupplier {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

* Functional interface for describing a method to supply AggregationDataStoreTransaction.
*/
@FunctionalInterface
public interface AggregationDataStoreTransactionCancel {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we shorten the name of this interface (we already know this is for the AggregationDataStore since it is an inner class).

public AggregationDataStoreTransaction(QueryEngine queryEngine) {
this.queryEngine = queryEngine;
private AggregationDataStore.AggregationDataStoreTransactionCancel aggregationDataStoreTransactionCancel;
public AggregationDataStoreTransaction(EntityManager em, QueryEngine queryEngine, AggregationDataStore.AggregationDataStoreTransactionCancel aggregationDataStoreTransactionCancel) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the entity manager from the constructor. The AggregationStore (other than the SQLQueryEngine) should not have a direct dependency on the EntityManager

this.em = em;
this.emWrapper = new EntityManagerWrapper(em);
this.jpaTransactionCancel = jpaTransactionCancel;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not implement cancel here so we don't have to redefine it in each subclass.

@@ -170,19 +171,25 @@ public DataStore buildDataStore(EntityManagerFactory entityManagerFactory, Query
ObjectProvider<ElideDynamicEntityCompiler> dynamicCompiler, ElideConfigProperties settings)
throws ClassNotFoundException {
AggregationDataStore aggregationDataStore = null;
JpaDataStore.JpaTransactionCancel jpaTransactionCancel = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be assigned like:

jpaTransactionCancel = (entityManager) -> { entityManager.unwrap(Session.class).cancelQuery();};

and then you can reuse jpaTransactionCancel below.

(em -> { return new NonJtaTransaction(em); }));

(em -> { return new NonJtaTransaction(em, em.unwrap(Session.class).cancelQuery()); }),
(entityManager -> { entityManager.unwrap(Session.class).cancelQuery();}));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right - why are we defining the cancel method twice here and passing it through two separate functions?

@@ -393,18 +393,19 @@ default DataStore getDataStore(MetaDataStore metaDataStore, AggregationDataStore
* @return AggregationDataStore object initialized.
*/
default AggregationDataStore getAggregationDataStore(QueryEngine queryEngine,
Optional<ElideDynamicEntityCompiler> optionalCompiler) {
Optional<ElideDynamicEntityCompiler> optionalCompiler, EntityManagerFactory entityManagerFactory) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove entityManagerFactory as an argument.

aggregationDataStore = new AggregationDataStore(queryEngine);
aggregationDataStore = new AggregationDataStore(
() -> { return entityManagerFactory.createEntityManager(); },
queryEngine, (entityManager -> { entityManager.unwrap(Session.class).cancelQuery();}));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We define the transaction cancel method four times. Let's define this once with a static, final variable and just use that everywhere.

@@ -163,7 +163,7 @@ private void populateMetaData(MetaDataStore metaDataStore) {
* @param query The query customized for a particular persistent storage or storage client
* @return query results
*/
public abstract QueryResult executeQuery(Query query);
public abstract FutureImplementation<QueryResult> executeQuery(Query query);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just return a Future here instead of the Implementation.


import java.util.concurrent.Future;

public abstract class FutureImplementation implements Future<QueryResult> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make this an inner class of the SQLQueryEngine - not abstract - and it can just call the TransactionCancel member.

this.entityManagerFactory = entityManagerFactory;
}
public boolean cancel(boolean mayInterruptIfRunning) {
transactionCancel.cancel(entityManagerFactory.createEntityManager());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this line creates a new session and then immediately cancels it. We want to close the existing session - not a new one.

super(metaDataStore, cache);
this.entityManagerFactory = entityManagerFactory;
this.referenceTable = new SQLReferenceTable(metaDataStore);
this.transactionCancel = transactionCancel;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several places where spacing is off.

}

public class FutureImplementation implements Future<QueryResult> {
private final TransactionCancel transactionCancel;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An inner class can reference the members of the outer class if it is not static. There is no need to:

  1. Define private members
  2. Have a constructor with arguments.

* Cancels transaction
*/
@Override
protected FutureImplementation(EntityManagerFactory entityManagerFactory, TransactionCancel transactionCancel) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's find a better name than FutureImplementation. How about QueryResultFuture?

this.transactionCancel = transactionCancel;
this.entityManagerFactory = entityManagerFactory;
}
public boolean cancel(boolean mayInterruptIfRunning) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @Override.

@@ -60,13 +61,14 @@
@Slf4j
public class SQLQueryEngine extends QueryEngine {
private final EntityManagerFactory entityManagerFactory;

private final TransactionCancel transactionCancel;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the implementation of executeQuery that returns a Future here.

this.transactionCancel = transactionCancel;
this.entityManagerFactory = entityManagerFactory;
}
public boolean cancel(boolean mayInterruptIfRunning) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing a lot of the other Future functions. There is more than just cancel.

@coveralls
Copy link
Collaborator

coveralls commented Jun 12, 2020

Coverage Status

Coverage decreased (-0.1%) to 80.536% when pulling 127517b on Rkr1992:implement-cancel-function into af132fd on yahoo:elide-5.x.

@@ -267,4 +267,9 @@ default boolean supportsPagination(Class<?> entityClass, FilterExpression expres
* @return UUID id
*/
UUID getRequestId();

/**
* cancel running transaction
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you mention in the comments that the implementation must be thread-safe?

if (entityProjection.getPagination() != null && entityProjection.getPagination().returnPageTotals()) {
entityProjection.getPagination().setPageTotals(result.getPageTotals());
queryResult = queryEngine.executeQuery(query);
queryResult.run();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to call run() here. Calling queryResult.get() should invoke queryResult.run()

}
return result.getData();
} catch (TransactionException e) {
throw new TransactionException(null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't set null here.

super(metaDataStore, cache);
this.entityManagerFactory = entityManagerFactory;
this.referenceTable = new SQLReferenceTable(metaDataStore);
public SQLQueryEngine(MetaDataStore mDStore, EntityManagerFactory emFactory, Cache cx, TransactionCancel txCancel) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cache is much more readable than cx. Can you revert back to the more readable variable names?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for mDStore, qEngine, emFactory, etc.

public void cancel(EntityManager entityManager);
}

public class QueryResultFuture<V> extends FutureTask<V> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This inner class is missing javadoc. The linter will complain.

transaction.begin();
return transaction;
}

@Override
public DataStoreTransaction beginTransaction() {
EntityManager entityManager = entityManagerSupplier.get();
JpaTransaction transaction = writeTransactionSupplier.get(entityManager);
JpaTransaction transaction = writeTransactionSupplier.get(entityManager, jpaTransactionCancel);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to pass transactionCancel as an argument to the supplier. When the supplier is created, it can have a reference to transactionSupplier through closure. Remove this extra argument.

@@ -96,7 +99,8 @@ public JpaDataStoreHarness() {

store = new JpaDataStore(
() -> { return emf.createEntityManager(); },
(entityManager) -> { return new NonJtaTransaction(entityManager); }
(entityManager, txCancel) -> { return new NonJtaTransaction(entityManager, txCancel); },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for example, there is no need to include txCancel as a parameter to the supplier. Rewrite like:

(entityManager) -> { return new NonJtaTransaction(entityManager, jpaTransactionCancel); }

@@ -56,6 +58,10 @@
* @return An instance of ElideDynamicEntityCompiler.
* @throws Exception Exception thrown.
*/

private final AbstractJpaTransaction.JpaTransactionCancel jTC = (e) -> { e.unwrap(Session.class).cancelQuery(); };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the signatures are the same, you may be able to define this once as a Function rather than the concrete types above - and just use the single reference below.

DataStore jpaDataStore = new JpaDataStore(
() -> { return entityManagerFactory.createEntityManager(); },
(em -> { return new NonJtaTransaction(em); }));
((em, txCancel) -> { return new NonJtaTransaction(em, txCancel); }),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove txCancel from the supplier.

@@ -56,6 +58,10 @@
*/
public interface ElideStandaloneSettings {
/* Elide settings */

public final AbstractJpaTransaction.JpaTransactionCancel JTC = (m) -> { m.unwrap(Session.class).cancelQuery(); };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See if these can be consolidated into a single variable using one of Java's built in Function classes.

@@ -8,7 +8,7 @@
import com.yahoo.elide.core.DataStoreTransaction;
import com.yahoo.elide.core.EntityDictionary;
import com.yahoo.elide.core.datastore.JPQLDataStore;
import com.yahoo.elide.datastores.jpa.transaction.AbstractJpaTransaction;
//import com.yahoo.elide.datastores.jpa.transaction.AbstractJpaTransaction;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.

this(entityManager, lookupUserTransaction(), jpaTransactionCancel);
}

public JtaTransaction(EntityManager entityManager, UserTransaction transaction, JpaTransactionCancel txCancel) {
public JtaTransaction(EntityManager entityManager, UserTransaction transaction, Consumer<EntityManager> txCancel) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unify the variable names txCancel and jpaTransactionCancel.

@@ -59,8 +60,7 @@
* @throws Exception Exception thrown.
*/

private final AbstractJpaTransaction.JpaTransactionCancel jTC = (e) -> { e.unwrap(Session.class).cancelQuery(); };
private final SQLQueryEngine.TransactionCancel txCancel = (em) -> { em.unwrap(Session.class).cancelQuery(); };
private final Consumer<EntityManager> func = (em) -> { em.unwrap(Session.class).cancelQuery(); };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

txCancel was a better name than func. I would change everywhere.

@@ -59,8 +59,7 @@
public interface ElideStandaloneSettings {
/* Elide settings */

public final AbstractJpaTransaction.JpaTransactionCancel JTC = (m) -> { m.unwrap(Session.class).cancelQuery(); };
public final SQLQueryEngine.TransactionCancel TXCANCEL = (m) -> { m.unwrap(Session.class).cancelQuery(); };
public final Consumer<EntityManager> FUNC = (em) -> { em.unwrap(Session.class).cancelQuery(); };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to TXCANCEL

@@ -157,6 +156,7 @@ private void populateMetaData(MetaDataStore metaDataStore) {
public interface Transaction extends AutoCloseable {
@Override
void close();
void cancel();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add javadoc for cancel (close isn't needed because it is an Override).

@aklish aklish merged commit ff86c56 into yahoo:elide-5.x Jun 17, 2020
aklish pushed a commit that referenced this pull request Jul 10, 2020
* implement cancel function

* addressing comments

* addressing comments

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* adding Future Task

* adding Future Task

* adding Future Task

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* ExecutionException

* fixing issues

* aggregation changes

* aggregation changes

* aggregation changes

* fixing bugs

* fixing bugs

* fixing bugs

* rebasing

* adddressing comments

* adddressing comments

* addressing comments

* addressing comments

Co-authored-by: Ramsha Rao <[email protected]>
aklish pushed a commit that referenced this pull request Aug 8, 2020
* implement cancel function

* addressing comments

* addressing comments

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* adding Future Task

* adding Future Task

* adding Future Task

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* ExecutionException

* fixing issues

* aggregation changes

* aggregation changes

* aggregation changes

* fixing bugs

* fixing bugs

* fixing bugs

* rebasing

* adddressing comments

* adddressing comments

* addressing comments

* addressing comments

Co-authored-by: Ramsha Rao <[email protected]>
aklish pushed a commit that referenced this pull request Sep 22, 2020
* implement cancel function

* addressing comments

* addressing comments

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* adding Future Task

* adding Future Task

* adding Future Task

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* ExecutionException

* fixing issues

* aggregation changes

* aggregation changes

* aggregation changes

* fixing bugs

* fixing bugs

* fixing bugs

* rebasing

* adddressing comments

* adddressing comments

* addressing comments

* addressing comments

Co-authored-by: Ramsha Rao <[email protected]>
aklish pushed a commit that referenced this pull request Nov 17, 2020
* implement cancel function

* addressing comments

* addressing comments

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* adding Future Task

* adding Future Task

* adding Future Task

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* ExecutionException

* fixing issues

* aggregation changes

* aggregation changes

* aggregation changes

* fixing bugs

* fixing bugs

* fixing bugs

* rebasing

* adddressing comments

* adddressing comments

* addressing comments

* addressing comments

Co-authored-by: Ramsha Rao <[email protected]>
aklish pushed a commit that referenced this pull request Dec 11, 2020
* implement cancel function

* addressing comments

* addressing comments

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* Future implementation

* adding Future Task

* adding Future Task

* adding Future Task

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing future implementation

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing issues

* fixing issues

* fixing issues

* fixing issues

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* fixing bugs

* ExecutionException

* fixing issues

* aggregation changes

* aggregation changes

* aggregation changes

* fixing bugs

* fixing bugs

* fixing bugs

* rebasing

* adddressing comments

* adddressing comments

* addressing comments

* addressing comments

Co-authored-by: Ramsha Rao <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants