Finalization

This commit is contained in:
Paldiu
2022-12-14 12:57:45 -06:00
parent 99c78e320f
commit 1687ca32f3
74 changed files with 2382 additions and 750 deletions

View File

@ -0,0 +1,221 @@
package io.github.simplexdevelopment.scheduler;
import io.github.simplexdevelopment.api.IService;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import reactor.core.publisher.Mono;
import java.util.Objects;
public abstract class ExecutableService implements IService {
/**
* The name of the service.
*/
private final String service_name;
/**
* How long the service should wait before executing the first time.
*/
private final long delay;
/**
* How long the service should wait between executions.
*/
private final long period;
/**
* If the service should be executed once or continuously.
*/
private final boolean repeating;
/**
* If the service should be allowed to stop while executing.
*/
private final boolean mayInterruptWhenRunning;
/**
* The service's execution thread.
*/
private ServicePool parentPool;
/**
* Whether the service has been cancelled or not.
*/
private boolean cancelled = false;
/**
* Creates a new instance of an executable service.
* Each service is registered with a {@link String},
* to allow for easy identification within the associated {@link ServicePool}.
*
* @param service_name A namespaced key which can be used to identify the service.
*/
public ExecutableService(@NotNull String service_name) {
this((new ServicePool("defaultPool" + SchedulingSystem.denom, false)),
service_name,
0L,
0L,
false,
false);
SchedulingSystem.denom++;
}
/**
* Creates a new instance of an executable service.
* Each service is registered with a {@link String},
* to allow for easy identification within the associated {@link ServicePool}.
*
* @param parentPool The {@link ServicePool} which this service is executing on.
* @param service_name A namespaced key which can be used to identify the service.
*/
public ExecutableService(@Nullable ServicePool parentPool, @NotNull String service_name) {
this(parentPool,
service_name,
0L,
0L,
false,
false);
}
/**
* Creates a new instance of an executable service.
* The timings are measured in ticks (20 ticks per second).
* You do not need to explicitly define a delay.
* Each service is registered with a {@link String},
* to allow for easy identification within the associated {@link ServicePool}.
*
* @param parentPool The {@link ServicePool} which this service is executing on.
* @param service_name A namespaced key which can be used to identify the service.
* @param delay A specified amount of time (in ticks) to wait before the service runs.
*/
public ExecutableService(
@Nullable ServicePool parentPool,
@NotNull String service_name,
@Nullable Long delay) {
this(parentPool,
service_name,
delay,
0L,
false,
false);
}
/**
* Creates a new instance of an executable service.
* The timings are measured in ticks (20 ticks per second).
* You do not need to explicitly define a delay or a period,
* however if you have flagged {@link #repeating} as true, and the period is null,
* then the period will automatically be set to 20 minutes.
* Each service is registered with a {@link String},
* to allow for easy identification within the associated {@link ServicePool}.
*
* @param parentPool The {@link ServicePool} which this service is executing on.
* @param service_name A namespaced key which can be used to identify the service.
* @param delay A specified amount of time (in ticks) to wait before the service runs.
* @param period How long the service should wait between service executions (in ticks).
* @param repeating If the service should be scheduled for repeated executions or not.
*/
public ExecutableService(
@Nullable ServicePool parentPool,
@NotNull String service_name,
@NotNull Long delay,
@NotNull Long period,
@NotNull Boolean repeating) {
this(parentPool,
service_name,
delay, period,
repeating,
false);
}
/**
* Creates a new instance of an executable service.
* The timings are measured in ticks (20 ticks per second).
* You do not need to explicitly define a delay or a period,
* however if you have flagged {@link #repeating} as true, and the period is null,
* then the period will automatically be set to 20 minutes.
* Each service is registered with a {@link String},
* to allow for easy identification within the associated {@link ServicePool}.
*
* @param parentPool The {@link ServicePool} which this service is executing on.
* @param service_name A namespaced key which can be used to identify the service.
* @param delay A specified amount of time (in ticks) to wait before the service runs.
* @param period How long the service should wait between service executions (in ticks).
* @param repeating If the service should be scheduled for repeated executions or not.
* @param mayInterruptWhenRunning If the service can be cancelled during execution.
*/
public ExecutableService(
@Nullable ServicePool parentPool,
@NotNull String service_name,
@Nullable Long delay,
@Nullable Long period,
@NotNull Boolean repeating,
@NotNull Boolean mayInterruptWhenRunning) {
this.service_name = service_name;
this.repeating = repeating;
this.delay = Objects.requireNonNullElse(delay, 0L);
this.period = Objects.requireNonNullElse(period, (20L * 60L) * 20L);
this.mayInterruptWhenRunning = mayInterruptWhenRunning;
this.parentPool = parentPool;
}
@Override
public long getDelay() {
return delay;
}
@Override
public long getPeriod() {
return period;
}
@Override
public boolean isPeriodic() {
return repeating;
}
/**
* Cancels the execution of this service.
*
* @return true if the service was cancelled, false if not.
*/
public boolean isCancelled() {
return this.cancelled;
}
/**
* Cancels the execution of this service.
*
* @param cancel Whether the service should be cancelled or not.
*/
public Mono<Void> setCancelled(boolean cancel) {
if (!mayInterruptWhenRunning) {
return Mono.empty();
}
cancelled = cancel;
return cancel();
}
/**
* Actual stop call, to ensure that the service actually #isCancelled().
*/
@Contract(pure = true)
Mono<Void> cancel() {
if (isCancelled()) {
return stop().then();
}
return Mono.empty();
}
@Override
public Mono<ServicePool> getParentPool() {
return Mono.just(parentPool);
}
@Override
public String getName() {
return service_name;
}
@Override
public Mono<Void> setParentPool(ServicePool servicePool) {
return Mono.just(servicePool).doOnNext(pool -> this.parentPool = pool).then();
}
}

View File

@ -40,7 +40,7 @@ public final class ReactorBukkitScheduler
* @return A disposable that can be used to cancel the task.
*/
@Override
public @NotNull Disposable schedule(@NotNull Runnable task, long delay, @Nullable TimeUnit unit) {
public @NotNull Disposable schedule(@NotNull Runnable task, long delay, @Deprecated @Nullable TimeUnit unit) {
return new BukkitDisposable(scheduler.runTaskLater(plugin, task, delay));
}
@ -56,7 +56,7 @@ public final class ReactorBukkitScheduler
* @return A disposable that can be used to cancel the task.
*/
@Override
public @NotNull Disposable schedulePeriodically(@NotNull Runnable task, long initialDelay, long period, @Nullable TimeUnit unit) {
public @NotNull Disposable schedulePeriodically(@NotNull Runnable task, long initialDelay, long period, @Deprecated @Nullable TimeUnit unit) {
if (period <= 0L) {
throw new IllegalArgumentException("Period must be greater than 0L");
}
@ -78,6 +78,7 @@ public final class ReactorBukkitScheduler
* This method does nothing and is unused.
*/
@Override
@Deprecated
public void dispose() {
}
}

View File

@ -6,40 +6,39 @@ import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import reactor.core.Disposable;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public final class SchedulingSystem<T extends JavaPlugin> implements ISchedule {
/**
* A denominator to use when registering default service pool names.
*/
static int denom = 0;
/**
* The service manager to use for controlling service pools.
*/
private final ServiceManager serviceManager;
/**
* The plugin to use for registering tasks. This should be an instance of your plugin.
*/
private final T plugin;
private final Set<ServicePool> repeatingPools;
/**
* The main scheduler which this system runs on. This is an abstraction of the {@link BukkitScheduler},
* and as a result runs on the Main server thread.
*/
private final ReactorBukkitScheduler mainScheduler;
/**
* Creates a new instance of the scheduling system. This is used to manage the scheduling of services.
*
* @param plugin The plugin to use for this scheduling system. This should be an instance of your plugin.
* @param plugin The plugin to use for this scheduling system. This should be an instance of your plugin.
*/
public SchedulingSystem(T plugin) {
this.serviceManager = new ServiceManager();
this.plugin = plugin;
this.repeatingPools = new HashSet<>();
this.mainScheduler = new ReactorBukkitScheduler(plugin);
}
/**
* @return A set of {@link ServicePool}s which contain repeating services.
*/
@Contract(pure = true)
public Set<ServicePool> getRepeatingPools() {
return repeatingPools;
}
@Override
public @NotNull Mono<ServiceManager> getServiceManager() {
return Mono.just(serviceManager);
@ -47,20 +46,19 @@ public final class SchedulingSystem<T extends JavaPlugin> implements ISchedule {
@Override
@NotNull
public Mono<ServicePool> queue(@NotNull IService service) {
return getServiceManager().flatMap(serviceManager -> {
Mono<ServicePool> pool = serviceManager.getAssociatedServicePool(service);
return pool.defaultIfEmpty(Objects.requireNonNull(serviceManager
.createServicePool(ServicePool.getDefaultNamespacedKey(), service)
.block()));
});
public Mono<Disposable> queue(@NotNull IService service) {
return getServiceManager()
.flatMap(manager -> manager.getAssociatedServicePool(service))
.flatMap(pool -> pool.queueService(service));
}
@Override
public @NotNull Mono<Void> runOnce(IService service) {
return Mono.just(service).doOnNext(s -> {
s.start().then(s.stop()).subscribe();
}).then();
return Mono.just(service)
.doOnNext(s -> s.start()
.then(s.stop())
.subscribe())
.then();
}
@Override

View File

@ -1,7 +1,6 @@
package io.github.simplexdevelopment.scheduler;
import io.github.simplexdevelopment.api.IService;
import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import reactor.core.publisher.Flux;
@ -12,6 +11,9 @@ import java.util.HashSet;
import java.util.Set;
public final class ServiceManager {
/**
* A set of {@link ServicePool}s which are currently active.
*/
private final Set<ServicePool> servicePools;
/**
@ -32,7 +34,7 @@ public final class ServiceManager {
* This service pool will execute each service consecutively within a singular non-blocking thread.
*/
@Contract(pure = true, value = "_, _ -> new")
public @NotNull Mono<ServicePool> createServicePool(NamespacedKey poolName, IService... services) {
public @NotNull Mono<ServicePool> createServicePool(String poolName, IService... services) {
ServicePool pool = new ServicePool(poolName, false);
Flux.fromIterable(Arrays.asList(services)).doOnEach(s -> pool.addService(s.get()));
return Mono.just(pool);
@ -45,7 +47,7 @@ public final class ServiceManager {
* This service pool will execute each service across a set of non-blocking threads.
*/
@Contract(pure = true, value = "_, _ -> new")
public @NotNull Mono<ServicePool> multithreadedServicePool(NamespacedKey name, IService... services) {
public @NotNull Mono<ServicePool> multithreadedServicePool(String name, IService... services) {
ServicePool pool = new ServicePool(name, true);
Flux.fromIterable(Arrays.asList(services)).doOnEach(s -> pool.addService(s.get()));
return Mono.just(pool);
@ -60,7 +62,7 @@ public final class ServiceManager {
* or by using {@link ServicePool#addService(IService)}.
*/
@Contract(pure = true, value = "_, _ -> new")
public @NotNull Mono<ServicePool> emptyServicePool(NamespacedKey poolName, boolean multithreaded) {
public @NotNull Mono<ServicePool> emptyServicePool(String poolName, boolean multithreaded) {
ServicePool pool = new ServicePool(poolName, multithreaded);
return Mono.just(pool);
}

View File

@ -1,7 +1,6 @@
package io.github.simplexdevelopment.scheduler;
import io.github.simplexdevelopment.api.IService;
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@ -18,9 +17,9 @@ import java.util.concurrent.TimeUnit;
public final class ServicePool {
/**
* The default {@link NamespacedKey} used to identify unmarked services. This will cause errors if left unchecked.
* The default {@link String} used to identify unmarked services. This will cause errors if left unchecked.
*/
private static final NamespacedKey DEFAULT = new NamespacedKey("simplex_ss", "default_service_pool");
private static final String DEFAULT = "default_service_pool";
/**
* A collection of services related to this service pool.
*/
@ -30,9 +29,9 @@ public final class ServicePool {
*/
private final Scheduler scheduler;
/**
* The key used to identify this service pool.
* The name used to identify this service pool.
*/
private final NamespacedKey name;
private final String name;
/**
* This will create a new instance of a Service Pool with a {@link Scheduler} as its main scheduler.
@ -41,7 +40,7 @@ public final class ServicePool {
* @param name The name of this service pool.
* @param multithreaded Whether this service pool should be multithreaded, or operate upon a single thread.
*/
public ServicePool(NamespacedKey name, boolean multithreaded) {
public ServicePool(String name, boolean multithreaded) {
this.name = name;
this.associatedServices = new HashSet<>();
if (multithreaded) {
@ -57,7 +56,7 @@ public final class ServicePool {
*
* @param name The name of this service pool.
*/
public ServicePool(NamespacedKey name, JavaPlugin plugin) {
public ServicePool(String name, JavaPlugin plugin) {
this.name = name;
this.associatedServices = new HashSet<>();
this.scheduler = new ReactorBukkitScheduler(plugin);
@ -66,7 +65,7 @@ public final class ServicePool {
/**
* @return The default namespaced key to use if one is not assigned.
*/
static NamespacedKey getDefaultNamespacedKey() {
static String getDefaultNamespacedKey() {
return DEFAULT;
}
@ -140,7 +139,7 @@ public final class ServicePool {
* @param disposable A {@link Disposable} object which contains the service that should be disposed.
* @return A {@link Mono<Void>} object which can be used to stop the service.
*/
public @NotNull Mono<Void> stopService(@NotNull NamespacedKey service_name, @Nullable Mono<Disposable> disposable) {
public @NotNull Mono<Void> stopService(@NotNull String service_name, @Nullable Mono<Disposable> disposable) {
getService(service_name).doOnNext(IService::stop).subscribe();
if (disposable != null) {
disposable.doOnNext(Disposable::dispose).subscribe();
@ -152,9 +151,9 @@ public final class ServicePool {
* @param service_name The name of the service to get.
* @return A {@link Mono} object which contains the service.
*/
public @NotNull Mono<IService> getService(NamespacedKey service_name) {
public @NotNull Mono<IService> getService(String service_name) {
return Flux.fromIterable(getAssociatedServices())
.filter(service -> service.getNamespacedKey().equals(service_name))
.filter(service -> service.getName().equals(service_name))
.next();
}