Skip to content

Commit

Permalink
Scheduler updated on api and impl
Browse files Browse the repository at this point in the history
- extract Constants
- constant for default name
- constants for names expressions
- servicePropery cron -> cronjob.cron and String[]
- fallback for old servicePropery cron
- hold tests of old servicePropery cron
- add test of old servicePropery cronjob.cron
- servicePropery name -> cronjob.name and define in api
- fallback for old servicePropery name
- use osgi converter in scheduler
- add Requirement and Capability annotation
- make corePoolSize configurable
- make shutdownTimeout(soft/hard) configurable
- fix fieldNames and javadoc
- add duration methods to Scheduler
- make parameterNames more expressiv

Signed-off-by: Stefan Bischof <stbischof@bipolis.org>
  • Loading branch information
stbischof authored and pkriens committed Sep 4, 2024
1 parent 14ca101 commit 73d17d1
Show file tree
Hide file tree
Showing 16 changed files with 298 additions and 69 deletions.
3 changes: 2 additions & 1 deletion biz.aQute.api/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
org.osgi.dto,\
org.apache.felix.http.servlet-api,\
org.osgi.service.component.annotations,\
org.osgi.namespace.extender
org.osgi.namespace.extender,\
org.osgi.service.metatype.annotations

-sub: *.bnd
83 changes: 83 additions & 0 deletions biz.aQute.api/src/main/java/biz/aQute/scheduler/api/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package biz.aQute.scheduler.api;

public final class Constants {

private Constants() {
// Constants
}

/**
* Specification Name
*/
public static final String SPECIFICATION_NAME = "aqute.scheduler";

/**
* Specification Version
*/
public static final String SPECIFICATION_VERSION = "1.1.0";

/**
* The service property Prefix for cronjobs
*/
public static final String SERVICE_PROPERTY_CRONJOB_PREFIX = "cronjob";

/**
* The service property that specifies the cron schedule. The type is String+.
*/
public static final String SERVICE_PROPERTY_CRONJOB_CRON = SERVICE_PROPERTY_CRONJOB_PREFIX+".cron";

/**
* The service property that specifies the name of the cron job. The type is
* String.
*/
public static final String SERVICE_PROPERTY_CRONJOB_NAME = SERVICE_PROPERTY_CRONJOB_PREFIX+".name";

/**
* Default name of the cron job.
*/
public static final String CRONJOB_NAME_DEFAULT = "unknown";

/**
* the named cron expression for annually execution.
*/
public static final String CRON_EXPRESSION_ANNUALLY = "@annually";

/**
* the named cron expression for yearly execution.
*/
public static final String CRON_EXPRESSION_YEARLY = "@yearly";

/**
* the named cron expression for monthly execution.
*/
public static final String CRON_EXPRESSION_MONTHLY = "@monthly";
/**
* the named cron expression for weekly execution.
*/
public static final String CRON_EXPRESSION_WEEKLY = "@weekly";

/**
* the named cron expression for daily execution.
*/
public static final String CRON_EXPRESSION_DAYLY = "@daily";

/**
* the named cron expression for hourly execution.
*/
public static final String CRON_EXPRESSION_HOURLY = "@hourly";

/**
* the named cron expression for minutely execution.
*/
public static final String CRON_EXPRESSION_MINUTLY = "@minutely";

/**
* the named cron expression for secondly execution.
*/
public static final String CRON_EXPRESSION_SECUNDLY = "@secondly";

/**
* the named cron expression for execution onreboot.
*/
public static final String CRON_EXPRESSION_REBOOT = "@reboot";
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
package biz.aQute.scheduler.api;

import org.osgi.service.component.annotations.ComponentPropertyType;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

/**
* An annotation to simplify using a CronJob
*/
@ComponentPropertyType
@ObjectClassDefinition
@RequireSchedulerImplementation
public @interface CronExpression {

public static final String PREFIX_ = Constants.SERVICE_PROPERTY_CRONJOB_PREFIX;
/**
* The 'cron.expression' service property
* The 'cronjob.cron' service property as defines in {@link Constants#SERVICE_PROPERTY_CRONJOB_CRON}
* @return
*/
String cron();
@AttributeDefinition(name="cronJobCronExpression", description = "Cron Expression according the Cron Spec. see http://en.wikipedia.org/wiki/Cron")
String[] cron();

/**
* The 'cronjob.name' service property as defines in {@link Constants#SERVIC_PROPERTY_CRON_NAME()()}
* @return
*/
@AttributeDefinition(name="cronJobName", description = "Human readable name of the cronjob")
String name() default Constants.CRONJOB_NAME_DEFAULT;


}

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* chronos.
* <p>
* The Unix Cron defines a syntax that is used by the Cron service. A user
* should register a Cron service with the {@value CronJob#CRON} property. The
* should register a Cron service with the {@value Constants#SERVICE_PROPERTY_CRONJOB_CRON} property. The
* value is according to the {link http://en.wikipedia.org/wiki/Cron}.
* <p>
*
Expand Down Expand Up @@ -77,8 +77,15 @@ public interface CronJob {
/**
* The service property that specifies the cron schedule. The type is
* String+.
* @deprecated use {@link Constants#SERVICE_PROPERTY_CRONJOB_CRON} "cronjob.cron";
*/
@Deprecated
String CRON = "cron";

/**
* @deprecated use {@link Constants#SERVICE_PROPERTY_CRONJOB_NAME} "cronjob.name";
*/
@Deprecated
String NAME = "name";

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package biz.aQute.scheduler.api;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import org.osgi.annotation.bundle.Requirement;
import org.osgi.namespace.implementation.ImplementationNamespace;

/**
* Require an implementation for the this specification
*/
@Requirement(namespace = ImplementationNamespace.IMPLEMENTATION_NAMESPACE, filter = "(&("
+ ImplementationNamespace.IMPLEMENTATION_NAMESPACE + "="
+ Constants.SPECIFICATION_NAME + ")${frange;${version;==;"
+ Constants.SPECIFICATION_VERSION + "}})")
@Retention(RetentionPolicy.CLASS)
public @interface RequireSchedulerImplementation {}
40 changes: 36 additions & 4 deletions biz.aQute.api/src/main/java/biz/aQute/scheduler/api/Scheduler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package biz.aQute.scheduler.api;

import java.time.Duration;
import java.time.temporal.TemporalAdjuster;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
Expand All @@ -21,12 +22,41 @@ interface RunnableWithException {
* Schedule a runnable to run periodically at a fixed rate. The schedule can
* be canceled by the returned task.
*
* @param runnable
* the task to run
* @param name
* The name of the task
* @param fixedRateInMs
* The fixed rate in milliseconds.
*
*/
Task periodic(Runnable runnable, long fixedRateInMs, String name);

/**
* Schedule a runnable to run periodically at a fixed rate. The schedule can
* be canceled by the returned task.
*
* @param runnable
* the task to run
* @param name
* The name of the task
* @param fixedRate
* The fixed rate in milliseconds.
*
*/
Task periodic(Runnable runnable, Duration fixedRate, String name);
/**
* Schedule a runnable to run after a certain time. The schedule can be
* canceled by the returned task if it was not yet canceled.
*
* @param name
* The name of the task
* @param runnable
* the task to run
* @param afterMs
* time in ms after the run is scheduled.
*/
Task periodic(Runnable runnable, long ms, String name);
Task after(Runnable runnable, long afterMs, String name);

/**
* Schedule a runnable to run after a certain time. The schedule can be
Expand All @@ -36,8 +66,10 @@ interface RunnableWithException {
* The name of the task
* @param runnable
* the task to run
* @param after
* duration after the run is scheduled.
*/
Task after(Runnable runnable, long ms, String name);
Task after(Runnable runnable, Duration after, String name);

/**
* Executes a task in the background, intended for short term tasks
Expand Down Expand Up @@ -69,7 +101,7 @@ interface RunnableWithException {

/**
* Schedule a runnable to be executed for the give cron expression (See
* {@link CronJob}). Every time when the cronExpression matches the current
* {@link CronExpression#expression()}). Every time when the cronExpression matches the current
* time, the runnable will be run. The method returns a closeable that can
* be used to stop scheduling. This variation does not take an environment
* object.
Expand All @@ -96,7 +128,7 @@ interface RunnableWithException {
* ZonedDateTime next = now.with(cron);
* </pre>
*
* @param cronExpression a Cron expression as specified in {@link CronJob}
* @param cronExpression a Cron expression as specified in {@link CronExpression#expression()}
* @return a Temporal Adjuster based on a cron expression
*/
TemporalAdjuster getCronAdjuster(String cronExpression);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@org.osgi.annotation.bundle.Export
@Version("1.0.0")
@Version(biz.aQute.scheduler.api.Constants.SPECIFICATION_VERSION)
package biz.aQute.scheduler.api;

import org.osgi.annotation.versioning.Version;
Expand Down
11 changes: 6 additions & 5 deletions biz.aQute.scheduler.basic.provider/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
slf4j.api,\
biz.aQute.api.scheduler,\
org.osgi.util.promise,\
aQute.libg,\
org.osgi.service.metatype.annotations
org.osgi.service.metatype.annotations,\
org.osgi.util.converter,\
org.osgi.namespace.implementation


-testpath: \
Expand All @@ -18,8 +19,8 @@
org.assertj.core,\
org.awaitility,\
biz.aQute.launchpad,\
aQute.libg,\
osgi.core, \
slf4j.api, \
org.osgi.util.function,\
slf4j.api,\
slf4j.simple

-conditionalpackage: aQute.lib*
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package biz.aQute.scheduler.basic.config;

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

/**
* Configuration for the scheduler. The scheduler is a singleton
*/

@ObjectClassDefinition
@ObjectClassDefinition( description = "Configuration for the scheduler. The scheduler is a singleton")
public @interface SchedulerConfig {
String PID = "biz.aQute.scheduler.basic";
String SYSTEM_DEFAULT_TIMEZONE = "system.default.timezone";
String DESCRIPTION = "Set the time zone. The default is the system default time zone. "
+ "If the time zone does not exist, an error is logged and the system default time zone is used.";
int COREPOOLSIZE_DEFAUL = 50;
int SHUTDOWNTIMEOUT_SOFT_DEFAUL = 500;
int SHUTDOWNTIMEOUT_HARD_DEFAUL = 5000;

/**
* Set the time zone. The default is the system default time zone. If the
* time zone does not exist, an error is logged and the system default time zone is
* used.
*/
@AttributeDefinition(description = DESCRIPTION)
String timeZone() default SYSTEM_DEFAULT_TIMEZONE;

@AttributeDefinition(description = "corePoolSize of ScheduledThreadPoolExecutor")
int corePoolSize() default COREPOOLSIZE_DEFAUL;

@AttributeDefinition(description = "Expected shutdownTimeout of ScheduledThreadPoolExecutor")
int shutdownTimeoutSoft() default SHUTDOWNTIMEOUT_SOFT_DEFAUL;

@AttributeDefinition(description = "Expected shutdownTimeout after the shutdownTimeoutSoft befor the shutdown of ScheduledThreadPoolExecutor is forced")
int shutdownTimeoutHard() default SHUTDOWNTIMEOUT_HARD_DEFAUL;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@org.osgi.annotation.bundle.Export
@Version("1.0.0")
@Version("1.1.0")
package biz.aQute.scheduler.basic.config;

import org.osgi.annotation.versioning.Version;
Expand Down
Loading

0 comments on commit 73d17d1

Please sign in to comment.