/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.lang;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.cache.event.CacheEntryEventFilter;
import javax.cache.event.CacheEntryListener;
import javax.cache.event.CacheEntryUpdatedListener;
import org.apache.ignite.cache.query.ContinuousQuery;
import org.apache.ignite.configuration.IgniteConfiguration;
/**
* If callback has this annotation then it will be executing in another thread.
* <p>
* Currently this annotation is supported for:
* <ol>
* <li>{@link ContinuousQuery} - {@link CacheEntryUpdatedListener} and {@link CacheEntryEventFilter}.</li>
* </ol>
* <p>
* For example, if {@link CacheEntryEventFilter filter} or {@link CacheEntryListener}
* has the annotation then callbacks will be executing to asyncCallback thread pool. It allows to use cache API
* in a callbacks. This thread pool can be configured by {@link IgniteConfiguration#setAsyncCallbackPoolSize(int)}.
* <h1 class="header">Example</h1>
* As an example, suppose we have cache with {@code 'Person'} objects and we need
* to query all persons with salary above then 1000. Also remote filter will update some entries.
* <p>
* Here is the {@code Person} class:
* <pre name="code" class="java">
* public class Person {
* // Name.
* private String name;
*
* // Salary.
* private double salary;
*
* ...
* }
* </pre>
* <p>
* Here is the {@code ExampleCacheEntryFilter} class:
* <pre name="code" class="java">
* @IgniteAsyncCallback
* public class ExampleCacheEntryFilter implements CacheEntryEventFilter<Integer, Person> {
* @IgniteInstanceResource
* private Ignite ignite;
*
* // Continuous listener will be notified for persons with salary above 1000.
* // Filter increases salary for some person on 100. Without @IgniteAsyncCallback annotation
* // this operation is not safe.
* public boolean evaluate(CacheEntryEvent<? extends K, ? extends V> evt) throws CacheEntryListenerException {
* Person p = evt.getValue();
*
* if (p.getSalary() > 1000)
* return true;
*
* ignite.cache("Person").put(evt.getKey(), new Person(p.getName(), p.getSalary() + 100));
*
* return false;
* }
* }
* </pre>
* <p>
* Query with asynchronous callback execute as usually:
* <pre name="code" class="java">
* // Create new continuous query.
* ContinuousQuery<Long, Person> qry = new ContinuousQuery<>();
*
* // Callback that is called locally when update notifications are received.
* // It simply prints out information about all created persons.
* qry.setLocalListener((evts) -> {
* for (CacheEntryEvent<? extends Long, ? extends Person> e : evts) {
* Person p = e.getValue();
*
* System.out.println(p.getFirstName() + " " + p.getLastName() + "'s salary is " + p.getSalary());
* }
* });
*
* // Sets remote filter.
* qry.setRemoteFilterFactory(() -> new ExampleCacheEntryFilter());
*
* // Execute query.
* QueryCursor<Cache.Entry<Long, Person>> cur = cache.query(qry);
* </pre>
*
* @see IgniteConfiguration#getAsyncCallbackPoolSize
* @see ContinuousQuery#getRemoteFilterFactory()
* @see ContinuousQuery#getLocalListener()
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IgniteAsyncCallback {
// No-op.
}