chore: Google sheet shared drive support added behind a flag (#37776)
## Description This PR hides shared drive support for Google Sheets Integration behind a feature flag as we need to do thorough testing for it. The feature flag implementation done in this PR involves passing feature flags from server to google sheets plugin module. This temporary feature flagging solution tech debt can be removed once the testing is done and once we would release this feature to all. **Why feature flags are only available at server module?** Because they have a dependency on UserIdentifierService, SessionUserService, TenantService etc which exists at server module. Supporting feature flags out of the box at plugin module level would require significant efforts to migrate these dependencies. Fixes #37714 _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Authentication, @tag.Datasource" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/12063930619> > Commit: 47f08f9903e78e050f18ad304dd736acb61b8b28 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12063930619&attempt=2" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Authentication, @tag.Datasource` > Spec: > <hr>Thu, 28 Nov 2024 07:38:58 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Introduced support for Google Sheets shared drive through feature flags. - Added new methods to handle feature flags in plugin execution and triggering processes. - Enhanced action execution and triggering logic to utilize feature flags for dynamic behavior. - **Bug Fixes** - Improved error handling for plugin execution processes. - **Tests** - Integrated `FeatureFlagService` into the testing framework for enhanced test coverage. - Expanded test scenarios to include various response types and error conditions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: “sneha122” <“sneha@appsmith.com”>
This commit is contained in:
parent
6a31cacba5
commit
8d32ee8f22
|
|
@ -14,6 +14,7 @@ public enum FeatureFlagEnum {
|
|||
APP_NAVIGATION_LOGO_UPLOAD,
|
||||
release_embed_hide_share_settings_enabled,
|
||||
rollout_datasource_test_rate_limit_enabled,
|
||||
release_google_sheets_shared_drive_support_enabled,
|
||||
|
||||
// Deprecated CE flags over here
|
||||
release_git_autocommit_feature_enabled,
|
||||
|
|
|
|||
|
|
@ -247,6 +247,50 @@ public interface PluginExecutor<C> extends ExtensionPoint, CrudTemplateService {
|
|||
.tap(Micrometer.observation(observationRegistry));
|
||||
}
|
||||
|
||||
// TODO: Following methods of executeParameterizedWithFlags, executeParameterizedWithMetricsAndFlags,
|
||||
// triggerWithFlags are
|
||||
// added
|
||||
// to support feature flags in the plugin modules. Current implementation of featureFlagService is only available in
|
||||
// server module
|
||||
// and not available in any of the plugin modules due to dependencies on SessionUserService, TenantService etc.
|
||||
// Hence, these methods are added to support feature flags in the plugin modules.
|
||||
// Ideal solution would be to move featureFlagService and its dependencies to the shared interface module
|
||||
// But this is a bigger change and will be done in future. Current change of passing flags was done to resolve
|
||||
// release blocker
|
||||
// https://github.com/appsmithorg/appsmith/issues/37714
|
||||
// Once thorogh testing of shared drive support is done, we can remove this tech debt of passing feature flags like
|
||||
// this.
|
||||
default Mono<ActionExecutionResult> executeParameterizedWithFlags(
|
||||
C connection,
|
||||
ExecuteActionDTO executeActionDTO,
|
||||
DatasourceConfiguration datasourceConfiguration,
|
||||
ActionConfiguration actionConfiguration,
|
||||
Map<String, Boolean> featureFlagMap) {
|
||||
return this.executeParameterized(connection, executeActionDTO, datasourceConfiguration, actionConfiguration);
|
||||
}
|
||||
|
||||
default Mono<ActionExecutionResult> executeParameterizedWithMetricsAndFlags(
|
||||
C connection,
|
||||
ExecuteActionDTO executeActionDTO,
|
||||
DatasourceConfiguration datasourceConfiguration,
|
||||
ActionConfiguration actionConfiguration,
|
||||
ObservationRegistry observationRegistry,
|
||||
Map<String, Boolean> featureFlagMap) {
|
||||
return this.executeParameterizedWithFlags(
|
||||
connection, executeActionDTO, datasourceConfiguration, actionConfiguration, featureFlagMap)
|
||||
.tag("plugin", this.getClass().getName())
|
||||
.name(ACTION_EXECUTION_PLUGIN_EXECUTION)
|
||||
.tap(Micrometer.observation(observationRegistry));
|
||||
}
|
||||
|
||||
default Mono<TriggerResultDTO> triggerWithFlags(
|
||||
C connection,
|
||||
DatasourceConfiguration datasourceConfiguration,
|
||||
TriggerRequestDTO request,
|
||||
Map<String, Boolean> featureFlagMap) {
|
||||
return this.trigger(connection, datasourceConfiguration, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is responsible for preparing the action and datasource configurations to be ready for execution.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -77,7 +77,9 @@ public interface ExecutionMethod {
|
|||
return Mono.just(true);
|
||||
}
|
||||
|
||||
WebClient.RequestHeadersSpec<?> getExecutionClient(WebClient webClient, MethodConfig methodConfig);
|
||||
default WebClient.RequestHeadersSpec<?> getExecutionClient(WebClient webClient, MethodConfig methodConfig) {
|
||||
return null;
|
||||
}
|
||||
|
||||
default JsonNode transformExecutionResponse(
|
||||
JsonNode response, MethodConfig methodConfig, Set<String> userAuthorizedSheetIds) {
|
||||
|
|
@ -102,4 +104,9 @@ public interface ExecutionMethod {
|
|||
conversionMap.put(DataType.FLOAT, DataType.DOUBLE);
|
||||
return conversionMap;
|
||||
}
|
||||
|
||||
default WebClient.RequestHeadersSpec<?> getExecutionClientWithFlags(
|
||||
WebClient webClient, MethodConfig methodConfig, Map<String, Boolean> featureFlagMap) {
|
||||
return getExecutionClient(webClient, methodConfig);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.external.config;
|
||||
|
||||
import com.appsmith.external.enums.FeatureFlagEnum;
|
||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
|
||||
import com.external.constants.ErrorMessages;
|
||||
import com.external.enums.GoogleSheetMethodEnum;
|
||||
|
|
@ -24,8 +25,9 @@ import static com.external.utils.SheetsUtil.getSpreadsheetData;
|
|||
* API reference: https://developers.google.com/sheets/api/guides/migration#list_spreadsheets_for_the_authenticated_user
|
||||
*/
|
||||
public class FileListMethod implements ExecutionMethod, TriggerMethod {
|
||||
|
||||
ObjectMapper objectMapper;
|
||||
private final String SHARED_DRIVE_PARAMS =
|
||||
"&includeItemsFromAllDrives=true&supportsAllDrives=true&corpora=allDrives";
|
||||
|
||||
public FileListMethod(ObjectMapper objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
|
|
@ -37,10 +39,16 @@ public class FileListMethod implements ExecutionMethod, TriggerMethod {
|
|||
}
|
||||
|
||||
@Override
|
||||
public WebClient.RequestHeadersSpec<?> getExecutionClient(WebClient webClient, MethodConfig methodConfig) {
|
||||
public WebClient.RequestHeadersSpec<?> getExecutionClientWithFlags(
|
||||
WebClient webClient, MethodConfig methodConfig, Map<String, Boolean> featureFlagMap) {
|
||||
// TODO: Flags are needed here for google sheets integration to support shared drive behind a flag
|
||||
// Once thoroughly tested, this flag can be removed
|
||||
Boolean isSharedDriveSupportEnabled = featureFlagMap.getOrDefault(
|
||||
FeatureFlagEnum.release_google_sheets_shared_drive_support_enabled.name(), Boolean.FALSE);
|
||||
UriComponentsBuilder uriBuilder = getBaseUriBuilder(
|
||||
this.BASE_DRIVE_API_URL,
|
||||
"?includeItemsFromAllDrives=true&supportsAllDrives=true&orderBy=name&q=mimeType%3D'application%2Fvnd.google-apps.spreadsheet'%20and%20trashed%3Dfalse",
|
||||
"?orderBy=name&q=mimeType%3D'application%2Fvnd.google-apps.spreadsheet'%20and%20trashed%3Dfalse"
|
||||
+ (isSharedDriveSupportEnabled.equals(Boolean.TRUE) ? SHARED_DRIVE_PARAMS : ""),
|
||||
true);
|
||||
|
||||
return webClient
|
||||
|
|
@ -74,8 +82,9 @@ public class FileListMethod implements ExecutionMethod, TriggerMethod {
|
|||
}
|
||||
|
||||
@Override
|
||||
public WebClient.RequestHeadersSpec<?> getTriggerClient(WebClient webClient, MethodConfig methodConfig) {
|
||||
return this.getExecutionClient(webClient, methodConfig);
|
||||
public WebClient.RequestHeadersSpec<?> getTriggerClientWithFlags(
|
||||
WebClient webClient, MethodConfig methodConfig, Map<String, Boolean> featureFlagMap) {
|
||||
return this.getExecutionClientWithFlags(webClient, methodConfig, featureFlagMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.external.config;
|
|||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
|
@ -21,7 +22,17 @@ public interface TriggerMethod {
|
|||
/**
|
||||
* Returns with the specification required to hit that particular trigger request
|
||||
*/
|
||||
WebClient.RequestHeadersSpec<?> getTriggerClient(WebClient webClient, MethodConfig methodConfig);
|
||||
default WebClient.RequestHeadersSpec<?> getTriggerClient(WebClient webClient, MethodConfig methodConfig) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns with the specification required to hit that particular trigger request
|
||||
*/
|
||||
default WebClient.RequestHeadersSpec<?> getTriggerClientWithFlags(
|
||||
WebClient webClient, MethodConfig methodConfig, Map<String, Boolean> featureFlagMap) {
|
||||
return getTriggerClient(webClient, methodConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the response from the end point into an Appsmith friendly structure
|
||||
|
|
|
|||
|
|
@ -81,6 +81,23 @@ public class GoogleSheetsPlugin extends BasePlugin {
|
|||
ExecuteActionDTO executeActionDTO,
|
||||
DatasourceConfiguration datasourceConfiguration,
|
||||
ActionConfiguration actionConfiguration) {
|
||||
return executeParameterizedWithFlags(
|
||||
connection, executeActionDTO, datasourceConfiguration, actionConfiguration, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<TriggerResultDTO> trigger(
|
||||
Void connection, DatasourceConfiguration datasourceConfiguration, TriggerRequestDTO request) {
|
||||
return triggerWithFlags(connection, datasourceConfiguration, request, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ActionExecutionResult> executeParameterizedWithFlags(
|
||||
Void connection,
|
||||
ExecuteActionDTO executeActionDTO,
|
||||
DatasourceConfiguration datasourceConfiguration,
|
||||
ActionConfiguration actionConfiguration,
|
||||
Map<String, Boolean> featureFlagMap) {
|
||||
|
||||
log.debug(Thread.currentThread().getName() + ": executeParameterized() called for GoogleSheets plugin.");
|
||||
boolean smartJsonSubstitution;
|
||||
|
|
@ -133,13 +150,14 @@ public class GoogleSheetsPlugin extends BasePlugin {
|
|||
|
||||
prepareConfigurationsForExecution(executeActionDTO, actionConfiguration, datasourceConfiguration);
|
||||
|
||||
return this.executeCommon(connection, datasourceConfiguration, actionConfiguration);
|
||||
return this.executeCommon(connection, datasourceConfiguration, actionConfiguration, featureFlagMap);
|
||||
}
|
||||
|
||||
public Mono<ActionExecutionResult> executeCommon(
|
||||
Void connection,
|
||||
DatasourceConfiguration datasourceConfiguration,
|
||||
ActionConfiguration actionConfiguration) {
|
||||
ActionConfiguration actionConfiguration,
|
||||
Map<String, Boolean> featureFlagMap) {
|
||||
|
||||
log.debug(Thread.currentThread().getName() + ": executeCommon() called for GoogleSheets plugin.");
|
||||
// Initializing object for error condition
|
||||
|
|
@ -185,7 +203,7 @@ public class GoogleSheetsPlugin extends BasePlugin {
|
|||
// method
|
||||
.flatMap(res -> {
|
||||
return executionMethod
|
||||
.getExecutionClient(client, methodConfig)
|
||||
.getExecutionClientWithFlags(client, methodConfig, featureFlagMap)
|
||||
.headers(headers -> headers.set(
|
||||
"Authorization",
|
||||
"Bearer "
|
||||
|
|
@ -319,8 +337,11 @@ public class GoogleSheetsPlugin extends BasePlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Mono<TriggerResultDTO> trigger(
|
||||
Void connection, DatasourceConfiguration datasourceConfiguration, TriggerRequestDTO request) {
|
||||
public Mono<TriggerResultDTO> triggerWithFlags(
|
||||
Void connection,
|
||||
DatasourceConfiguration datasourceConfiguration,
|
||||
TriggerRequestDTO request,
|
||||
Map<String, Boolean> featureFlagMap) {
|
||||
log.debug(Thread.currentThread().getName() + ": trigger() called for GoogleSheets plugin.");
|
||||
final TriggerMethod triggerMethod = GoogleSheetsMethodStrategy.getTriggerMethod(request, objectMapper);
|
||||
MethodConfig methodConfig = new MethodConfig(request);
|
||||
|
|
@ -343,7 +364,7 @@ public class GoogleSheetsPlugin extends BasePlugin {
|
|||
validateAndGetUserAuthorizedSheetIds(datasourceConfiguration, methodConfig);
|
||||
|
||||
return triggerMethod
|
||||
.getTriggerClient(client, methodConfig)
|
||||
.getTriggerClientWithFlags(client, methodConfig, featureFlagMap)
|
||||
.headers(headers -> headers.set(
|
||||
"Authorization",
|
||||
"Bearer " + oauth2.getAuthenticationResponse().getToken()))
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.appsmith.server.exceptions.AppsmithException;
|
|||
import com.appsmith.server.helpers.PluginExecutorHelper;
|
||||
import com.appsmith.server.repositories.PluginRepository;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.FeatureFlagService;
|
||||
import com.appsmith.server.services.TenantService;
|
||||
import com.appsmith.server.solutions.DatasourceTriggerSolution;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
|
@ -28,18 +29,21 @@ public class PluginTriggerSolutionCEImpl implements PluginTriggerSolutionCE {
|
|||
private final PluginRepository pluginRepository;
|
||||
private final ConfigService configService;
|
||||
private final TenantService tenantService;
|
||||
private final FeatureFlagService featureFlagService;
|
||||
|
||||
public PluginTriggerSolutionCEImpl(
|
||||
DatasourceTriggerSolution datasourceTriggerSolution,
|
||||
PluginExecutorHelper pluginExecutorHelper,
|
||||
PluginRepository pluginRepository,
|
||||
ConfigService configService,
|
||||
TenantService tenantService) {
|
||||
TenantService tenantService,
|
||||
FeatureFlagService featureFlagService) {
|
||||
this.datasourceTriggerSolution = datasourceTriggerSolution;
|
||||
this.pluginExecutorHelper = pluginExecutorHelper;
|
||||
this.pluginRepository = pluginRepository;
|
||||
this.configService = configService;
|
||||
this.tenantService = tenantService;
|
||||
this.featureFlagService = featureFlagService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,6 +78,11 @@ public class PluginTriggerSolutionCEImpl implements PluginTriggerSolutionCE {
|
|||
Mono<PluginExecutor> pluginExecutorMono =
|
||||
pluginMono.flatMap(plugin -> pluginExecutorHelper.getPluginExecutor(Mono.just(plugin)));
|
||||
|
||||
// TODO: Flags are needed here for google sheets integration to support shared drive behind a flag
|
||||
// Once thoroughly tested, this flag can be removed
|
||||
Map<String, Boolean> featureFlagMap =
|
||||
featureFlagService.getCachedTenantFeatureFlags().getFeatures();
|
||||
|
||||
/*
|
||||
* Since there is no datasource provided, we are passing the Datasource Context connection and datasourceConfiguration as null.
|
||||
* We will leave the execution to respective plugin executor.
|
||||
|
|
@ -83,8 +92,8 @@ public class PluginTriggerSolutionCEImpl implements PluginTriggerSolutionCE {
|
|||
PluginExecutor pluginExecutor = pair.getT2();
|
||||
setHeadersToTriggerRequest(plugin, httpHeaders, triggerRequestDTO);
|
||||
return setTenantAndInstanceId(triggerRequestDTO)
|
||||
.flatMap(updatedTriggerRequestDTO ->
|
||||
((PluginExecutor<Object>) pluginExecutor).trigger(null, null, updatedTriggerRequestDTO));
|
||||
.flatMap(updatedTriggerRequestDTO -> ((PluginExecutor<Object>) pluginExecutor)
|
||||
.triggerWithFlags(null, null, updatedTriggerRequestDTO, featureFlagMap));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.appsmith.server.plugins.solutions;
|
|||
import com.appsmith.server.helpers.PluginExecutorHelper;
|
||||
import com.appsmith.server.repositories.PluginRepository;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.FeatureFlagService;
|
||||
import com.appsmith.server.services.TenantService;
|
||||
import com.appsmith.server.solutions.DatasourceTriggerSolution;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -14,7 +15,14 @@ public class PluginTriggerSolutionImpl extends PluginTriggerSolutionCEImpl imple
|
|||
PluginExecutorHelper pluginExecutorHelper,
|
||||
PluginRepository pluginRepository,
|
||||
ConfigService configService,
|
||||
TenantService tenantService) {
|
||||
super(datasourceTriggerSolution, pluginExecutorHelper, pluginRepository, configService, tenantService);
|
||||
TenantService tenantService,
|
||||
FeatureFlagService featureFlagService) {
|
||||
super(
|
||||
datasourceTriggerSolution,
|
||||
pluginExecutorHelper,
|
||||
pluginRepository,
|
||||
configService,
|
||||
tenantService,
|
||||
featureFlagService);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.appsmith.server.services.AnalyticsService;
|
|||
import com.appsmith.server.services.AuthenticationValidator;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.DatasourceContextService;
|
||||
import com.appsmith.server.services.FeatureFlagService;
|
||||
import com.appsmith.server.services.SessionUserService;
|
||||
import com.appsmith.server.services.TenantService;
|
||||
import com.appsmith.server.solutions.ce.ActionExecutionSolutionCEImpl;
|
||||
|
|
@ -42,7 +43,8 @@ public class ActionExecutionSolutionImpl extends ActionExecutionSolutionCEImpl i
|
|||
ConfigService configService,
|
||||
TenantService tenantService,
|
||||
CommonConfig commonConfig,
|
||||
ActionExecutionSolutionHelper actionExecutionSolutionHelper) {
|
||||
ActionExecutionSolutionHelper actionExecutionSolutionHelper,
|
||||
FeatureFlagService featureFlagService) {
|
||||
super(
|
||||
newActionService,
|
||||
actionPermission,
|
||||
|
|
@ -63,6 +65,7 @@ public class ActionExecutionSolutionImpl extends ActionExecutionSolutionCEImpl i
|
|||
configService,
|
||||
tenantService,
|
||||
commonConfig,
|
||||
actionExecutionSolutionHelper);
|
||||
actionExecutionSolutionHelper,
|
||||
featureFlagService);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.appsmith.server.plugins.base.PluginService;
|
|||
import com.appsmith.server.services.AuthenticationValidator;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.DatasourceContextService;
|
||||
import com.appsmith.server.services.FeatureFlagService;
|
||||
import com.appsmith.server.services.TenantService;
|
||||
import com.appsmith.server.solutions.ce.DatasourceTriggerSolutionCEImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
@ -28,7 +29,8 @@ public class DatasourceTriggerSolutionImpl extends DatasourceTriggerSolutionCEIm
|
|||
DatasourcePermission datasourcePermission,
|
||||
EnvironmentPermission environmentPermission,
|
||||
ConfigService configService,
|
||||
TenantService tenantService) {
|
||||
TenantService tenantService,
|
||||
FeatureFlagService featureFlagService) {
|
||||
super(
|
||||
datasourceService,
|
||||
datasourceStorageService,
|
||||
|
|
@ -40,6 +42,7 @@ public class DatasourceTriggerSolutionImpl extends DatasourceTriggerSolutionCEIm
|
|||
datasourcePermission,
|
||||
environmentPermission,
|
||||
configService,
|
||||
tenantService);
|
||||
tenantService,
|
||||
featureFlagService);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import com.appsmith.server.services.AnalyticsService;
|
|||
import com.appsmith.server.services.AuthenticationValidator;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.DatasourceContextService;
|
||||
import com.appsmith.server.services.FeatureFlagService;
|
||||
import com.appsmith.server.services.SessionUserService;
|
||||
import com.appsmith.server.services.TenantService;
|
||||
import com.appsmith.server.solutions.ActionPermission;
|
||||
|
|
@ -73,6 +74,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
|
|
@ -122,6 +124,7 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
private final TenantService tenantService;
|
||||
private final ActionExecutionSolutionHelper actionExecutionSolutionHelper;
|
||||
private final CommonConfig commonConfig;
|
||||
private final FeatureFlagService featureFlagService;
|
||||
|
||||
static final String PARAM_KEY_REGEX = "^k\\d+$";
|
||||
static final String BLOB_KEY_REGEX =
|
||||
|
|
@ -150,7 +153,8 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
ConfigService configService,
|
||||
TenantService tenantService,
|
||||
CommonConfig commonConfig,
|
||||
ActionExecutionSolutionHelper actionExecutionSolutionHelper) {
|
||||
ActionExecutionSolutionHelper actionExecutionSolutionHelper,
|
||||
FeatureFlagService featureFlagService) {
|
||||
this.newActionService = newActionService;
|
||||
this.actionPermission = actionPermission;
|
||||
this.observationRegistry = observationRegistry;
|
||||
|
|
@ -171,6 +175,7 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
this.tenantService = tenantService;
|
||||
this.commonConfig = commonConfig;
|
||||
this.actionExecutionSolutionHelper = actionExecutionSolutionHelper;
|
||||
this.featureFlagService = featureFlagService;
|
||||
|
||||
this.patternList.add(Pattern.compile(PARAM_KEY_REGEX));
|
||||
this.patternList.add(Pattern.compile(BLOB_KEY_REGEX));
|
||||
|
|
@ -726,13 +731,20 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
// Now that we have the context (connection details), execute the action.
|
||||
|
||||
Instant requestedAt = Instant.now();
|
||||
Map<String, Boolean> features = featureFlagService.getCachedTenantFeatureFlags() != null
|
||||
? featureFlagService.getCachedTenantFeatureFlags().getFeatures()
|
||||
: Collections.emptyMap();
|
||||
|
||||
// TODO: Flags are needed here for google sheets integration to support shared drive behind a flag
|
||||
// Once thoroughly tested, this flag can be removed
|
||||
return ((PluginExecutor<Object>) pluginExecutor)
|
||||
.executeParameterizedWithMetrics(
|
||||
.executeParameterizedWithMetricsAndFlags(
|
||||
resourceContext.getConnection(),
|
||||
executeActionDTO,
|
||||
datasourceStorage1.getDatasourceConfiguration(),
|
||||
actionDTO.getActionConfiguration(),
|
||||
observationRegistry)
|
||||
observationRegistry,
|
||||
features)
|
||||
.map(actionExecutionResult -> {
|
||||
ActionExecutionRequest actionExecutionRequest = actionExecutionResult.getRequest();
|
||||
if (actionExecutionRequest == null) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.appsmith.server.plugins.base.PluginService;
|
|||
import com.appsmith.server.services.AuthenticationValidator;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.DatasourceContextService;
|
||||
import com.appsmith.server.services.FeatureFlagService;
|
||||
import com.appsmith.server.services.TenantService;
|
||||
import com.appsmith.server.solutions.DatasourcePermission;
|
||||
import com.appsmith.server.solutions.DatasourceStructureSolution;
|
||||
|
|
@ -27,6 +28,7 @@ import reactor.core.publisher.Mono;
|
|||
import reactor.util.function.Tuple2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -53,6 +55,7 @@ public class DatasourceTriggerSolutionCEImpl implements DatasourceTriggerSolutio
|
|||
private final EnvironmentPermission environmentPermission;
|
||||
private final ConfigService configService;
|
||||
private final TenantService tenantService;
|
||||
private final FeatureFlagService featureFlagService;
|
||||
|
||||
public Mono<TriggerResultDTO> trigger(
|
||||
String datasourceId, String environmentId, TriggerRequestDTO triggerRequestDTO) {
|
||||
|
|
@ -104,6 +107,12 @@ public class DatasourceTriggerSolutionCEImpl implements DatasourceTriggerSolutio
|
|||
final Plugin plugin = tuple.getT2();
|
||||
final PluginExecutor pluginExecutor = tuple.getT3();
|
||||
|
||||
// TODO: Flags are needed here for google sheets integration to support shared drive behind a flag
|
||||
// Once thoroughly tested, this flag can be removed
|
||||
Map<String, Boolean> featureFlagMap = featureFlagService.getCachedTenantFeatureFlags() != null
|
||||
? featureFlagService.getCachedTenantFeatureFlags().getFeatures()
|
||||
: Collections.emptyMap();
|
||||
|
||||
return datasourceContextService
|
||||
.getDatasourceContext(datasourceStorage, plugin)
|
||||
// Now that we have the context (connection details), execute the action.
|
||||
|
|
@ -111,10 +120,11 @@ public class DatasourceTriggerSolutionCEImpl implements DatasourceTriggerSolutio
|
|||
// However the context comes from evaluated datasource.
|
||||
.flatMap(resourceContext -> setTenantAndInstanceId(triggerRequestDTO)
|
||||
.flatMap(updatedTriggerRequestDTO -> ((PluginExecutor<Object>) pluginExecutor)
|
||||
.trigger(
|
||||
.triggerWithFlags(
|
||||
resourceContext.getConnection(),
|
||||
datasourceStorage.getDatasourceConfiguration(),
|
||||
updatedTriggerRequestDTO)));
|
||||
updatedTriggerRequestDTO,
|
||||
featureFlagMap)));
|
||||
});
|
||||
|
||||
// If the plugin hasn't implemented the trigger function, go for the default implementation
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.appsmith.server.services.AnalyticsService;
|
|||
import com.appsmith.server.services.AuthenticationValidator;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.DatasourceContextService;
|
||||
import com.appsmith.server.services.FeatureFlagService;
|
||||
import com.appsmith.server.services.SessionUserService;
|
||||
import com.appsmith.server.services.TenantService;
|
||||
import com.appsmith.server.solutions.ActionPermission;
|
||||
|
|
@ -136,6 +137,9 @@ class ActionExecutionSolutionCEImplTest {
|
|||
@SpyBean
|
||||
ActionExecutionSolutionHelper actionExecutionSolutionHelper;
|
||||
|
||||
@SpyBean
|
||||
FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
EnvironmentPermission environmentPermission;
|
||||
|
||||
|
|
@ -167,7 +171,8 @@ class ActionExecutionSolutionCEImplTest {
|
|||
configService,
|
||||
tenantService,
|
||||
commonConfig,
|
||||
actionExecutionSolutionHelper);
|
||||
actionExecutionSolutionHelper,
|
||||
featureFlagService);
|
||||
|
||||
ObservationRegistry.ObservationConfig mockObservationConfig =
|
||||
Mockito.mock(ObservationRegistry.ObservationConfig.class);
|
||||
|
|
|
|||
|
|
@ -327,6 +327,8 @@ public class ActionExecutionSolutionCETest {
|
|||
Mockito.when(pluginExecutorHelper.getPluginExecutor(any())).thenReturn(Mono.just(pluginExecutor));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetrics(any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.just(mockResult));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetricsAndFlags(any(), any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.just(mockResult));
|
||||
Mockito.when(pluginExecutor.datasourceCreate(any())).thenReturn(Mono.empty());
|
||||
Mockito.doReturn(Mono.just(false))
|
||||
.when(spyDatasourceService)
|
||||
|
|
@ -527,6 +529,8 @@ public class ActionExecutionSolutionCETest {
|
|||
Mockito.when(pluginExecutorHelper.getPluginExecutor(any())).thenReturn(Mono.just(pluginExecutor));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetrics(any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.error(pluginException));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetricsAndFlags(any(), any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.error(pluginException));
|
||||
Mockito.when(pluginExecutor.datasourceCreate(any())).thenReturn(Mono.empty());
|
||||
Mockito.doReturn(Mono.just(false))
|
||||
.when(spyDatasourceService)
|
||||
|
|
@ -584,6 +588,8 @@ public class ActionExecutionSolutionCETest {
|
|||
Mockito.when(pluginExecutorHelper.getPluginExecutor(any())).thenReturn(Mono.just(pluginExecutor));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetrics(any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.error(pluginException));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetricsAndFlags(any(), any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.error(pluginException));
|
||||
Mockito.when(pluginExecutor.datasourceCreate(any())).thenReturn(Mono.empty());
|
||||
Mockito.doReturn(Mono.just(false))
|
||||
.when(spyDatasourceService)
|
||||
|
|
@ -635,6 +641,9 @@ public class ActionExecutionSolutionCETest {
|
|||
Mockito.when(pluginExecutor.executeParameterizedWithMetrics(any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.error(new StaleConnectionException()))
|
||||
.thenReturn(Mono.error(new StaleConnectionException()));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetricsAndFlags(any(), any(), any(), any(), any(), any()))
|
||||
.thenReturn(Mono.error(new StaleConnectionException()))
|
||||
.thenReturn(Mono.error(new StaleConnectionException()));
|
||||
Mockito.when(pluginExecutor.datasourceCreate(any())).thenReturn(Mono.empty());
|
||||
Mockito.doReturn(Mono.just(false))
|
||||
.when(spyDatasourceService)
|
||||
|
|
@ -686,6 +695,8 @@ public class ActionExecutionSolutionCETest {
|
|||
Mockito.when(pluginExecutorHelper.getPluginExecutor(any())).thenReturn(Mono.just(pluginExecutor));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetrics(any(), any(), any(), any(), any()))
|
||||
.thenAnswer(x -> Mono.delay(Duration.ofMillis(1000)).ofType(ActionExecutionResult.class));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetricsAndFlags(any(), any(), any(), any(), any(), any()))
|
||||
.thenAnswer(x -> Mono.delay(Duration.ofMillis(1000)).ofType(ActionExecutionResult.class));
|
||||
Mockito.when(pluginExecutor.datasourceCreate(any())).thenReturn(Mono.empty());
|
||||
Mockito.doReturn(Mono.just(false))
|
||||
.when(spyDatasourceService)
|
||||
|
|
@ -716,8 +727,9 @@ public class ActionExecutionSolutionCETest {
|
|||
|
||||
Mockito.when(pluginExecutorHelper.getPluginExecutor(any())).thenReturn(Mono.just(pluginExecutor));
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetrics(any(), any(), any(), any(), any()))
|
||||
.thenThrow(new StaleConnectionException())
|
||||
.thenReturn(Mono.just(mockResult));
|
||||
.thenThrow(new StaleConnectionException());
|
||||
Mockito.when(pluginExecutor.executeParameterizedWithMetricsAndFlags(any(), any(), any(), any(), any(), any()))
|
||||
.thenThrow(new StaleConnectionException());
|
||||
Mockito.when(pluginExecutor.datasourceCreate(any())).thenReturn(Mono.empty());
|
||||
Mockito.when(pluginExecutor.getHintMessages(any(), any()))
|
||||
.thenReturn(Mono.zip(Mono.just(new HashSet<>()), Mono.just(new HashSet<>())));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user