All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.elide.spring.config.ElideAsyncConfiguration Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2019, Yahoo Inc.
 * Licensed under the Apache License, Version 2.0
 * See LICENSE file in project root for terms.
 */
package com.yahoo.elide.spring.config;

import static com.yahoo.elide.annotation.LifeCycleHookBinding.Operation.CREATE;
import static com.yahoo.elide.annotation.LifeCycleHookBinding.TransactionPhase.POSTCOMMIT;
import static com.yahoo.elide.annotation.LifeCycleHookBinding.TransactionPhase.PREFLUSH;
import static com.yahoo.elide.annotation.LifeCycleHookBinding.TransactionPhase.PRESECURITY;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;

import com.yahoo.elide.RefreshableElide;
import com.yahoo.elide.async.AsyncSettings.AsyncSettingsBuilder;
import com.yahoo.elide.async.DefaultResultTypeFileExtensionMapper;
import com.yahoo.elide.async.ResultTypeFileExtensionMapper;
import com.yahoo.elide.async.export.formatter.CsvExportFormatter;
import com.yahoo.elide.async.export.formatter.JsonExportFormatter;
import com.yahoo.elide.async.export.formatter.TableExportFormatter;
import com.yahoo.elide.async.export.formatter.TableExportFormatters;
import com.yahoo.elide.async.export.formatter.TableExportFormatters.TableExportFormattersBuilder;
import com.yahoo.elide.async.export.formatter.TableExportFormattersBuilderCustomizer;
import com.yahoo.elide.async.export.formatter.XlsxExportFormatter;
import com.yahoo.elide.async.hooks.AsyncQueryHook;
import com.yahoo.elide.async.hooks.TableExportHook;
import com.yahoo.elide.async.models.AsyncQuery;
import com.yahoo.elide.async.models.ResultType;
import com.yahoo.elide.async.models.TableExport;
import com.yahoo.elide.async.service.AsyncCleanerService;
import com.yahoo.elide.async.service.AsyncExecutorService;
import com.yahoo.elide.async.service.AsyncProviderService;
import com.yahoo.elide.async.service.AsyncProviderService.AsyncProviderServiceBuilder;
import com.yahoo.elide.async.service.AsyncProviderServiceBuilderCustomizer;
import com.yahoo.elide.async.service.dao.AsyncApiDao;
import com.yahoo.elide.async.service.dao.DefaultAsyncApiDao;
import com.yahoo.elide.async.service.storageengine.FileResultStorageEngine;
import com.yahoo.elide.async.service.storageengine.ResultStorageEngine;
import com.yahoo.elide.core.dictionary.EntityDictionary;
import com.yahoo.elide.graphql.QueryRunners;
import com.yahoo.elide.jsonapi.JsonApi;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Async Configuration For Elide Services.  Override any of the beans (by defining your own)
 * and setting flags to disable in properties to change the default behavior.
 */
@Configuration
@ConditionalOnClass(AsyncSettingsBuilder.class)
@ConditionalOnProperty(prefix = "elide.async", name = "enabled", matchIfMissing = false)
@AutoConfigurationPackage(basePackageClasses = AsyncQuery.class)
@EnableConfigurationProperties(ElideConfigProperties.class)
public class ElideAsyncConfiguration {

    /**
     * Creates the {@link TableExportFormattersBuilder}.
     * 

* Defining a {@link TableExportFormattersBuilderCustomizer} will allow customization of the default builder. * * @param elide elideObject * @param settings Elide settings. * @param customizerProvider the customizers * @return the TableExportFormattersBuilder */ @Bean @ConditionalOnMissingBean @Scope(SCOPE_PROTOTYPE) TableExportFormattersBuilder tableExportFormattersBuilder( RefreshableElide elide, ElideConfigProperties settings, ObjectProvider customizerProvider) { AsyncProperties asyncProperties = settings.getAsync(); TableExportFormattersBuilder builder = TableExportFormatters.builder(); // Initialize the Formatters. boolean writeCSVHeader = asyncProperties.getExport() != null && asyncProperties.getExport().getFormat().getCsv().isWriteHeader(); builder.entry(ResultType.CSV, new CsvExportFormatter(elide.getElide(), writeCSVHeader)); builder.entry(ResultType.JSON, new JsonExportFormatter(elide.getElide())); builder.entry(ResultType.XLSX, new XlsxExportFormatter(elide.getElide(), true)); customizerProvider.orderedStream().forEach(customizer -> customizer.customize(builder)); return builder; } /** * Configure the AsyncExecutorService used for submitting async query requests. * @param elide elideObject. * @param settings Elide settings. * @param asyncQueryDao AsyncDao object. * @param optionalResultStorageEngine Result Storage Engine. * @param tableExportFormattersBuilder TableExportFormattersBuilder. * @param asyncProviderService the AsyncProviderService. * @return a AsyncExecutorService. */ @Bean @ConditionalOnMissingBean AsyncExecutorService asyncExecutorService( RefreshableElide elide, ElideConfigProperties settings, AsyncApiDao asyncQueryDao, Optional optionalResultStorageEngine, TableExportFormattersBuilder tableExportFormattersBuilder, ResultTypeFileExtensionMapper resultTypeFileExtensionMapper, AsyncProviderService asyncProviderService ) { AsyncProperties asyncProperties = settings.getAsync(); ExecutorService executor = Executors.newFixedThreadPool(asyncProperties.getThreadPoolSize()); ExecutorService updater = Executors.newFixedThreadPool(asyncProperties.getThreadPoolSize()); AsyncExecutorService asyncExecutorService = new AsyncExecutorService(elide.getElide(), executor, updater, asyncQueryDao, asyncProviderService); // Binding AsyncQuery LifeCycleHook AsyncQueryHook asyncQueryHook = new AsyncQueryHook(asyncExecutorService, asyncProperties.getMaxAsyncAfter()); EntityDictionary dictionary = elide.getElide().getElideSettings().getEntityDictionary(); dictionary.bindTrigger(AsyncQuery.class, CREATE, PREFLUSH, asyncQueryHook, false); dictionary.bindTrigger(AsyncQuery.class, CREATE, POSTCOMMIT, asyncQueryHook, false); dictionary.bindTrigger(AsyncQuery.class, CREATE, PRESECURITY, asyncQueryHook, false); boolean exportEnabled = ElideAutoConfiguration.isExportEnabled(asyncProperties); if (exportEnabled) { // Binding TableExport LifeCycleHook TableExportHook tableExportHook = getTableExportHook(asyncExecutorService, settings, tableExportFormattersBuilder.build(), optionalResultStorageEngine.orElse(null), asyncProperties.getExport().isAppendFileExtension() ? resultTypeFileExtensionMapper : null); dictionary.bindTrigger(TableExport.class, CREATE, PREFLUSH, tableExportHook, false); dictionary.bindTrigger(TableExport.class, CREATE, POSTCOMMIT, tableExportHook, false); dictionary.bindTrigger(TableExport.class, CREATE, PRESECURITY, tableExportHook, false); } return asyncExecutorService; } private TableExportHook getTableExportHook(AsyncExecutorService asyncExecutorService, ElideConfigProperties settings, Map supportedFormatters, ResultStorageEngine resultStorageEngine, ResultTypeFileExtensionMapper resultTypeFileExtensionMapper) { return new TableExportHook(asyncExecutorService, settings.getAsync().getMaxAsyncAfter(), supportedFormatters, resultStorageEngine, resultTypeFileExtensionMapper); } /** * Configure the AsyncCleanerService used for cleaning up async query requests. * @param elide elideObject. * @param settings Elide settings. * @param asyncQueryDao AsyncDao object. * @return a AsyncCleanerService. */ @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "elide.async.cleanup", name = "enabled", matchIfMissing = false) AsyncCleanerService asyncCleanerService(RefreshableElide elide, ElideConfigProperties settings, AsyncApiDao asyncQueryDao) { AsyncCleanerService.init(elide.getElide(), settings.getAsync().getCleanup().getQueryMaxRunTime(), settings.getAsync().getCleanup().getQueryRetentionDuration(), settings.getAsync().getCleanup().getQueryCancellationCheckInterval(), asyncQueryDao); return AsyncCleanerService.getInstance(); } /** * Configure the AsyncQueryDAO used by async query requests. * @param elide elideObject. * @return an AsyncQueryDAO object. */ @Bean @ConditionalOnMissingBean AsyncApiDao asyncApiDao(RefreshableElide elide) { return new DefaultAsyncApiDao(elide.getElide().getElideSettings(), elide.getElide().getDataStore()); } /** * Configure the ResultStorageEngine used by async query requests. * @param settings Elide settings. * @return an ResultStorageEngine object. */ @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "elide.async.export", name = "enabled", matchIfMissing = false) ResultStorageEngine resultStorageEngine(ElideConfigProperties settings) { FileResultStorageEngine resultStorageEngine = new FileResultStorageEngine( settings.getAsync().getExport().getStorageDestination()); return resultStorageEngine; } /** * Configure the mapping of result type file extension. * @return the ResultTypeFileExtensionMapper */ @Bean @ConditionalOnMissingBean ResultTypeFileExtensionMapper resultTypeFileExtensionMapper() { return new DefaultResultTypeFileExtensionMapper(); } /** * Creates the {@link AsyncProviderServiceBuilder} to provide the underlying * services like JsonApi and QueryRunners. *

* Defining a {@link AsyncProviderServiceBuilderCustomizer} will allow * customization of the default builder. * * @param customizerProvider the customizers * @return the AsyncProviderServiceBuilder */ @Bean @ConditionalOnMissingBean @Scope(SCOPE_PROTOTYPE) AsyncProviderServiceBuilder asyncProviderServiceBuilder( ObjectProvider customizerProvider) { AsyncProviderServiceBuilder builder = AsyncProviderService.builder(); customizerProvider.orderedStream().forEach(customizer -> customizer.customize(builder)); return builder; } /** * Configure the {@link AsyncProviderService} to provide the underlying services like * JsonApi and QueryRunners. * * @param builder the builder * @return the AsyncProviderService */ @Bean @ConditionalOnMissingBean AsyncProviderService asyncProviderService(AsyncProviderServiceBuilder builder) { return builder.build(); } @Configuration @ConditionalOnClass(QueryRunners.class) @ConditionalOnProperty(prefix = "elide.graphql", name = "enabled", matchIfMissing = false) public static class GraphQLConfiguration { /** * Adds the GraphQL QueryRunners to the AsyncProviderService. * * @param queryRunners the query runnners * @return the customizer */ @Bean AsyncProviderServiceBuilderCustomizer graphQlAsyncProviderServiceBuilderCustomizer(QueryRunners queryRunners) { return builder -> { builder.provider(QueryRunners.class, queryRunners); }; } } @Configuration @ConditionalOnClass(JsonApi.class) @ConditionalOnProperty(prefix = "elide.json-api", name = "enabled", matchIfMissing = false) public static class JsonApiConfiguration { /** * Adds the JsonApi to the AsyncProviderService. * * @param jsonApi the json api * @return the customizer */ @Bean AsyncProviderServiceBuilderCustomizer jsonApiAsyncProviderServiceBuilderCustomizer(JsonApi jsonApi) { return builder -> { builder.provider(JsonApi.class, jsonApi); }; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy