Skip to content
Merged

2629 #3308

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
1 change: 1 addition & 0 deletions server/apps/server-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ dependencies {
implementation(project(":server:ee:libs:platform:platform-custom-component:platform-custom-component-configuration:platform-custom-component-configuration-service"))
implementation(project(":server:ee:libs:platform:platform-custom-component:platform-custom-component-file-storage:platform-custom-component-file-storage-impl"))
implementation(project(":server:ee:libs:platform:platform-scheduler:platform-scheduler-aws"))
implementation(project(":server:ee:libs:platform:platform-scheduler:platform-scheduler-impl"))
implementation(project(":server:ee:libs:platform:platform-security-web:platform-security-web-impl"))

implementation(project(":server:ee:libs:modules:components:api-platform"))
Expand Down
3 changes: 2 additions & 1 deletion server/ee/apps/scheduler-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ dependencies {
implementation(project(":server:ee:libs:config:observability-config"))
implementation(project(":server:ee:libs:core:discovery:discovery-redis"))
implementation(project(":server:ee:libs:platform:platform-component:platform-component-remote-client"))
implementation(project(":server:ee:libs:platform:platform-workflow:platform-workflow-execution:platform-workflow-execution-remote-client"))
implementation(project(":server:ee:libs:platform:platform-scheduler:platform-scheduler-impl"))
implementation(project(":server:ee:libs:platform:platform-scheduler:platform-scheduler-remote-rest"))
implementation(project(":server:ee:libs:platform:platform-workflow:platform-workflow-execution:platform-workflow-execution-remote-client"))

runtimeOnly("org.postgresql:postgresql")
runtimeOnly("com.zaxxer:HikariCP")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dependencies {
implementation("org.springframework:spring-context-support")
implementation("org.springframework:spring-jdbc")
implementation("org.springframework.boot:spring-boot-autoconfigure")
implementation("org.quartz-scheduler:quartz")
implementation(project(":server:libs:config:app-config"))
implementation(project(":server:libs:core:tenant:tenant-api"))
implementation(project(":server:libs:platform:platform-api"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2025 ByteChef
*
* Licensed under the ByteChef Enterprise license (the "Enterprise License");
* you may not use this file except in compliance with the Enterprise License.
*/

package com.bytechef.ee.platform.scheduler.config;

import com.bytechef.config.ApplicationProperties;
import com.bytechef.ee.platform.scheduler.tenant.MultiTenantLocalDataSourceJobStore;
import com.bytechef.platform.annotation.ConditionalOnEEVersion;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Properties;
import org.quartz.spi.JobFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.quartz.QuartzProperties;
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

/**
* @version ee
*
* @author Ivica Cardic
*/
@Configuration
@ConditionalOnProperty(
prefix = "bytechef", name = "coordinator.trigger.scheduler.provider", havingValue = "quartz", matchIfMissing = true)
@ConditionalOnEEVersion
public class MultiTenantQuartzTriggerSchedulerConfiguration implements SchedulerFactoryBeanCustomizer {

private final JobFactory jobFactory;
private final ApplicationProperties.Tenant.Mode mode;
private final QuartzProperties quartzProperties;

@SuppressFBWarnings("EI")
public MultiTenantQuartzTriggerSchedulerConfiguration(
ApplicationProperties applicationProperties, JobFactory jobFactory, QuartzProperties quartzProperties) {

this.jobFactory = jobFactory;
this.mode = applicationProperties.getTenant()
.getMode();
this.quartzProperties = quartzProperties;
}

@Override
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
schedulerFactoryBean.setJobFactory(jobFactory);

Properties properties = new Properties();

properties.putAll(quartzProperties.getProperties());

if (mode == ApplicationProperties.Tenant.Mode.MULTI) {
properties.put("org.quartz.jobStore.class", MultiTenantLocalDataSourceJobStore.class.getName());
}

schedulerFactoryBean.setQuartzProperties(properties);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
/*
* Copyright 2025 ByteChef
*
* Licensed 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
*
* https://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.
* Licensed under the ByteChef Enterprise license (the "Enterprise License");
* you may not use this file except in compliance with the Enterprise License.
*/

package com.bytechef.platform.scheduler.tenant;
package com.bytechef.ee.platform.scheduler.tenant;

import com.bytechef.tenant.TenantContext;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
Expand All @@ -40,8 +31,11 @@
import org.quartz.spi.OperableTrigger;

/**
* @version ee
*
* @author Ivica Cardic
*/
@SuppressFBWarnings("SQL_INJECTION_JDBC")
public class MultiTenantDriverDelegate extends StdJDBCDelegate {

private final DriverDelegate delegate;
Expand All @@ -54,6 +48,7 @@ public MultiTenantDriverDelegate(DriverDelegate delegate) {
@Override
public int updateTriggerStatesFromOtherStates(Connection conn, String newState, String oldState1, String oldState2)
throws SQLException {

return execute(conn, (connection) -> delegate.updateTriggerStatesFromOtherStates(
connection, newState, oldState1, oldState2));
}
Expand Down Expand Up @@ -167,6 +162,7 @@ public int updateJobData(Connection conn, JobDetail job) throws IOException, SQL
@Override
public JobDetail selectJobDetail(Connection conn, JobKey jobKey, ClassLoadHelper loadHelper)
throws ClassNotFoundException, IOException, SQLException {

return execute(conn, (connection) -> {
try {
return delegate.selectJobDetail(connection, jobKey, loadHelper);
Expand Down Expand Up @@ -194,6 +190,7 @@ public Set<JobKey> selectJobsInGroup(Connection conn, GroupMatcher<JobKey> match
@Override
public int insertTrigger(Connection conn, OperableTrigger trigger, String state, JobDetail jobDetail)
throws SQLException, IOException {

return execute(conn, (connection) -> {
try {
return delegate.insertTrigger(connection, trigger, state, jobDetail);
Expand All @@ -206,6 +203,7 @@ public int insertTrigger(Connection conn, OperableTrigger trigger, String state,
@Override
public int updateTrigger(Connection conn, OperableTrigger trigger, String state, JobDetail jobDetail)
throws SQLException, IOException {

return execute(conn, (connection) -> {
try {
return delegate.updateTrigger(connection, trigger, state, jobDetail);
Expand Down Expand Up @@ -334,6 +332,7 @@ public List<OperableTrigger> selectTriggersForCalendar(Connection conn, String c
@Override
public OperableTrigger selectTrigger(Connection conn, TriggerKey triggerKey)
throws SQLException, ClassNotFoundException, IOException, JobPersistenceException {

return execute(conn, (connection) -> {
try {
return delegate.selectTrigger(connection, triggerKey);
Expand All @@ -346,6 +345,7 @@ public OperableTrigger selectTrigger(Connection conn, TriggerKey triggerKey)
@Override
public JobDataMap selectTriggerJobDataMap(Connection conn, String triggerName, String groupName)
throws SQLException, ClassNotFoundException, IOException {

return execute(conn, (connection) -> {
try {
return delegate.selectTriggerJobDataMap(connection, triggerName, groupName);
Expand Down Expand Up @@ -458,6 +458,7 @@ public boolean calendarExists(Connection conn, String calendarName) throws SQLEx
@Override
public Calendar selectCalendar(Connection conn, String calendarName)
throws ClassNotFoundException, IOException, SQLException {

return execute(conn, (connection) -> {
try {
return delegate.selectCalendar(connection, calendarName);
Expand Down Expand Up @@ -506,6 +507,7 @@ public List<TriggerKey> selectTriggerToAcquire(Connection conn, long noLaterThan
@Override
public List<TriggerKey> selectTriggerToAcquire(Connection conn, long noLaterThan, long noEarlierThan, int maxCount)
throws SQLException {

return execute(conn, (connection) -> delegate.selectTriggerToAcquire(
connection, noLaterThan, noEarlierThan, maxCount));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
/*
* Copyright 2025 ByteChef
*
* Licensed 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
*
* https://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.
* Licensed under the ByteChef Enterprise license (the "Enterprise License");
* you may not use this file except in compliance with the Enterprise License.
*/

package com.bytechef.platform.scheduler.tenant;
package com.bytechef.ee.platform.scheduler.tenant;

import org.quartz.impl.jdbcjobstore.DriverDelegate;
import org.quartz.impl.jdbcjobstore.NoSuchDelegateException;
import org.quartz.impl.jdbcjobstore.Semaphore;
import org.springframework.scheduling.quartz.LocalDataSourceJobStore;

/**
* @version ee
*
* @author Ivica Cardic
*/
public class MultiTenantLocalDataSourceJobStore extends LocalDataSourceJobStore {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
/*
* Copyright 2025 ByteChef
*
* Licensed 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
*
* https://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.
* Licensed under the ByteChef Enterprise license (the "Enterprise License");
* you may not use this file except in compliance with the Enterprise License.
*/

package com.bytechef.platform.scheduler.tenant;
package com.bytechef.ee.platform.scheduler.tenant;

import com.bytechef.tenant.TenantContext;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.function.Function;
import org.quartz.impl.jdbcjobstore.LockException;
import org.quartz.impl.jdbcjobstore.Semaphore;

/**
* @version ee
*
* @author Ivica Cardic
*/
@SuppressFBWarnings("SQL_INJECTION_JDBC")
public class MultiTenantSemaphore implements Semaphore {

private final Semaphore semaphore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
* limitations under the License.
*/

package com.bytechef.platform.configuration.workflow.connection;
package com.bytechef.component.script.workflow.connection;

import com.bytechef.platform.component.definition.ScriptComponentDefinition;
import com.bytechef.platform.component.domain.ComponentDefinition;
import com.bytechef.platform.component.service.ComponentDefinitionService;
import com.bytechef.platform.configuration.domain.ComponentConnection;
import com.bytechef.platform.configuration.workflow.connection.ComponentConnectionFactory;
import com.bytechef.platform.configuration.workflow.connection.ComponentConnectionFactoryResolver;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @author Ivica Cardic
*/
@Component
@Order(3)
@Order
class DefaultComponentConnectionFactory
implements ComponentConnectionFactory, ComponentConnectionFactoryResolver {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,55 +19,25 @@
import com.bytechef.config.ApplicationProperties;
import com.bytechef.platform.scheduler.QuartzTriggerScheduler;
import com.bytechef.platform.scheduler.TriggerScheduler;
import com.bytechef.platform.scheduler.tenant.MultiTenantLocalDataSourceJobStore;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Properties;
import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.quartz.QuartzProperties;
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

/**
* @author Ivica Cardic
*/
@Configuration
@ConditionalOnProperty(
prefix = "bytechef", name = "coordinator.trigger.scheduler.provider", havingValue = "quartz", matchIfMissing = true)
public class QuartzTriggerSchedulerConfiguration implements SchedulerFactoryBeanCustomizer {

private final ApplicationProperties.Tenant.Mode mode;
private final QuartzProperties quartzProperties;

@SuppressFBWarnings("EI")
public QuartzTriggerSchedulerConfiguration(
ApplicationProperties applicationProperties, QuartzProperties quartzProperties) {

this.mode = applicationProperties.getTenant()
.getMode();
this.quartzProperties = quartzProperties;
}

@Override
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
schedulerFactoryBean.setJobFactory(jobFactory());

Properties properties = new Properties();

properties.putAll(quartzProperties.getProperties());

if (mode == ApplicationProperties.Tenant.Mode.MULTI) {
properties.put("org.quartz.jobStore.class", MultiTenantLocalDataSourceJobStore.class.getName());
}

schedulerFactoryBean.setQuartzProperties(properties);
}
public class QuartzTriggerSchedulerConfiguration {

@Bean
JobFactory jobFactory() {
Expand Down
Loading