mirror of
https://github.com/SimplexDevelopment/SimplexSS.git
synced 2025-07-01 14:46:42 +00:00
Doccing and Bugfixing
This commit is contained in:
@ -17,6 +17,48 @@ public abstract class ExecutableService implements IService {
|
||||
private final boolean mayInterruptWhenRunning;
|
||||
|
||||
private boolean cancelled = false;
|
||||
private ServicePool parentPool;
|
||||
|
||||
/**
|
||||
* Creates a new instance of an executable service.
|
||||
* Each service is registered with a {@link NamespacedKey},
|
||||
* 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 NamespacedKey service_name) {
|
||||
this((new ServicePool(IService.newNamespacedKey("", ""), false)), service_name, 0L, 0L, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of an executable service.
|
||||
* Each service is registered with a {@link NamespacedKey},
|
||||
* 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 NamespacedKey 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 NamespacedKey},
|
||||
* 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 NamespacedKey service_name,
|
||||
@Nullable Long delay) {
|
||||
this(parentPool, service_name, delay, 0L, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of an executable service.
|
||||
@ -27,6 +69,31 @@ public abstract class ExecutableService implements IService {
|
||||
* Each service is registered with a {@link NamespacedKey},
|
||||
* 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 NamespacedKey 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 NamespacedKey},
|
||||
* 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).
|
||||
@ -34,6 +101,7 @@ public abstract class ExecutableService implements IService {
|
||||
* @param mayInterruptWhenRunning If the service can be cancelled during execution.
|
||||
*/
|
||||
public ExecutableService(
|
||||
@Nullable ServicePool parentPool,
|
||||
@NotNull NamespacedKey service_name,
|
||||
@Nullable Long delay,
|
||||
@Nullable Long period,
|
||||
@ -44,6 +112,7 @@ public abstract class ExecutableService implements IService {
|
||||
this.delay = Objects.requireNonNullElse(delay, 0L);
|
||||
this.period = Objects.requireNonNullElse(period, (20L * 60L) * 20L);
|
||||
this.mayInterruptWhenRunning = mayInterruptWhenRunning;
|
||||
this.parentPool = parentPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,4 +168,9 @@ public abstract class ExecutableService implements IService {
|
||||
}
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ServicePool> getParentPool() {
|
||||
return Mono.just(parentPool);
|
||||
}
|
||||
}
|
||||
|
@ -68,4 +68,16 @@ public interface IService extends Runnable {
|
||||
.orElseThrow(InvalidServicePoolException.supplyException()))
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an easy static call for creating a new namespaced key for services and service pools.
|
||||
*
|
||||
* @param space The namespace of the service.
|
||||
* @param key The key name of the service.
|
||||
* @return A NamespacedKey object representing the service.
|
||||
*/
|
||||
@Contract("_, _ -> new")
|
||||
static @NotNull NamespacedKey newNamespacedKey(String space, String key) {
|
||||
return new NamespacedKey(space, key);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import java.util.function.Supplier;
|
||||
|
||||
public class InvalidServiceException extends RuntimeException {
|
||||
public InvalidServiceException(IService service) {
|
||||
super("The service " + service.getNamespacedKey().getKey() + " has encountered an exception.");
|
||||
super("The service " + service.getNamespacedKey().getKey() + " is not present within any service pool.");
|
||||
}
|
||||
|
||||
public InvalidServiceException(Throwable th) {
|
||||
|
@ -1,7 +1,9 @@
|
||||
package io.github.simplex.impl;
|
||||
|
||||
import io.github.simplex.api.IService;
|
||||
import io.github.simplex.simplexss.SchedulingSystem;
|
||||
import io.github.simplex.simplexss.ServiceManager;
|
||||
import io.github.simplex.simplexss.ServicePool;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Flux;
|
||||
@ -9,6 +11,7 @@ import reactor.core.publisher.Flux;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Main extends JavaPlugin {
|
||||
public ServicePool pool = new ServicePool(IService.newNamespacedKey("pool", "one"), true);
|
||||
private SchedulingSystem<Main> scheduler;
|
||||
private Flux<Disposable> disposables;
|
||||
|
||||
@ -16,10 +19,8 @@ public class Main extends JavaPlugin {
|
||||
public void onEnable() {
|
||||
ServiceManager serviceManager = new ServiceManager();
|
||||
this.scheduler = new SchedulingSystem<>(serviceManager, this);
|
||||
scheduler.getServiceManager().subscribe(manager -> manager.getServicePools()
|
||||
.doOnEach(signal -> disposables = Objects.requireNonNull(signal.get()).startServices())
|
||||
.subscribeOn(scheduler.getMainSchedulerThread(), false)
|
||||
.subscribe());
|
||||
IService service = new ServiceImpl(this);
|
||||
service.getParentPool().subscribe(element -> disposables = element.startServices());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,7 +10,7 @@ public class ServiceImpl extends ExecutableService {
|
||||
private final Main plugin;
|
||||
|
||||
public ServiceImpl(Main plugin) {
|
||||
super(IService.getDefaultNamespacedKey(), 20L, 20L * 60L * 10L, true, true);
|
||||
super(plugin.pool, IService.getDefaultNamespacedKey(), 0L, 20 * 60 * 20L, true, false);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,12 @@ public final class SchedulingSystem<T extends JavaPlugin> implements ISchedule {
|
||||
private final Set<ServicePool> repeatingPools;
|
||||
private final Scheduler mainScheduler;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the scheduling system. This is used to manage the scheduling of services.
|
||||
*
|
||||
* @param serviceManager The service manager to use for this scheduling system.
|
||||
* @param plugin The plugin to use for this scheduling system. This should be an instance of your plugin.
|
||||
*/
|
||||
public SchedulingSystem(@NotNull ServiceManager serviceManager, T plugin) {
|
||||
this.serviceManager = serviceManager;
|
||||
this.plugin = plugin;
|
||||
@ -53,8 +59,7 @@ public final class SchedulingSystem<T extends JavaPlugin> implements ISchedule {
|
||||
@Override
|
||||
public @NotNull Mono<Void> runOnce(IService service) {
|
||||
return Mono.just(service).doOnNext(s -> {
|
||||
s.start().subscribe();
|
||||
s.stop().subscribe();
|
||||
s.start().then(s.stop()).subscribe();
|
||||
}).then();
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,13 @@ import java.util.Set;
|
||||
public final class ServiceManager {
|
||||
private final Set<ServicePool> servicePools;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the Service Manager class.
|
||||
* This class acts as a Service Pool factory, and can be used to create
|
||||
* both single and multithreaded Service Pools, empty service pools, as well as
|
||||
* retrieve existing Service Pools. It also provides methods for you to add and remove
|
||||
* {@link IService}s from the {ServicePool} parameter.
|
||||
*/
|
||||
public ServiceManager() {
|
||||
servicePools = new HashSet<>();
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package io.github.simplex.simplexss;
|
||||
|
||||
import io.github.simplex.api.IService;
|
||||
import io.github.simplex.api.InvalidServiceException;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@ -12,16 +13,31 @@ import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class ServicePool {
|
||||
/**
|
||||
* A collection of services related to this service pool.
|
||||
*/
|
||||
private final Set<IService> associatedServices;
|
||||
/**
|
||||
* The scheduler used to run the services in this pool.
|
||||
*/
|
||||
private final Scheduler scheduler;
|
||||
/**
|
||||
* The key used to identify this service pool.
|
||||
*/
|
||||
private final NamespacedKey name;
|
||||
/**
|
||||
* The default {@link NamespacedKey} used to identify unmarked services. This will cause errors if left unchecked.
|
||||
*/
|
||||
private static final NamespacedKey DEFAULT = new NamespacedKey("simplex_ss", "default_service_pool");
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
this.name = name;
|
||||
this.associatedServices = new HashSet<>();
|
||||
@ -32,24 +48,44 @@ public final class ServicePool {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The default namespaced key to use if one is not assigned.
|
||||
*/
|
||||
static NamespacedKey getDefaultNamespacedKey() {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param service Add a service to the pool's service collection.
|
||||
*/
|
||||
void addService(IService service) {
|
||||
getAssociatedServices().add(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param service The service to check against this pool.
|
||||
* @return Whether the service is registered with this pool.
|
||||
*/
|
||||
boolean isValidService(IService service) {
|
||||
return getAssociatedServices().contains(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link Set} of {@link IService} objects which are registered with this pool.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@NotNull
|
||||
public Set<IService> getAssociatedServices() {
|
||||
return associatedServices;
|
||||
}
|
||||
|
||||
public Mono<Disposable> startService(NamespacedKey service_name) {
|
||||
/**
|
||||
* @param service_name The name of the service to queue. This should be a service that is located within this service pool.
|
||||
* If you name a service that is stored within another service pool,
|
||||
* this method will throw an error.
|
||||
* @return A {@link Mono} object which contains a {@link Disposable} element which can be used to destroy the registered service.
|
||||
*/
|
||||
public @NotNull Mono<Disposable> queueService(NamespacedKey service_name) {
|
||||
Mono<IService> service = getService(service_name);
|
||||
return service.map(s -> {
|
||||
if (s.isPeriodic()) {
|
||||
@ -65,7 +101,11 @@ public final class ServicePool {
|
||||
});
|
||||
}
|
||||
|
||||
public Flux<Disposable> startServices() {
|
||||
/**
|
||||
* @return A {@link Flux} object which contains a collection of {@link Disposable} elements,
|
||||
* which can be used to destroy the registered services using {@link ServicePool#stopServices(Flux<Disposable>)}.
|
||||
*/
|
||||
public @NotNull Flux<Disposable> startServices() {
|
||||
return Mono.just(getAssociatedServices()).flatMapMany(services -> {
|
||||
Set<Disposable> disposables = new HashSet<>();
|
||||
for (IService service : services) {
|
||||
@ -84,30 +124,58 @@ public final class ServicePool {
|
||||
});
|
||||
}
|
||||
|
||||
public Mono<Void> stopServices(Flux<Disposable> disposableThread) {
|
||||
/**
|
||||
* @param disposableThread A {@link Flux<Disposable>} which contains all the services that should be disposed..
|
||||
* @return A {@link Mono<Void>} object which can be used to stop the services.
|
||||
*/
|
||||
public @NotNull Mono<Void> stopServices(@NotNull Flux<Disposable> disposableThread) {
|
||||
getAssociatedServices().forEach(service -> service.stop().subscribe());
|
||||
return disposableThread.doOnNext(Disposable::dispose).then();
|
||||
}
|
||||
|
||||
public Mono<Void> stopService(NamespacedKey service_name) {
|
||||
return getService(service_name).doOnNext(IService::stop).then();
|
||||
/**
|
||||
* @param service_name The name of the service to stop.
|
||||
* @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) {
|
||||
getService(service_name).doOnNext(IService::stop).subscribe();
|
||||
if (disposable != null) {
|
||||
disposable.doOnNext(Disposable::dispose).subscribe();
|
||||
}
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
public Mono<IService> getService(NamespacedKey service_name) {
|
||||
/**
|
||||
* @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) {
|
||||
return Flux.fromIterable(getAssociatedServices())
|
||||
.filter(service -> service.getNamespacedKey().equals(service_name))
|
||||
.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param service The service to remove from the pool's service collection.
|
||||
*/
|
||||
void removeService(IService service) {
|
||||
getAssociatedServices().remove(service);
|
||||
}
|
||||
|
||||
public Mono<ServicePool> recycle() {
|
||||
/**
|
||||
* @return This service pool after being cleared of all services.
|
||||
* You will need to register services with this pool again before using it.
|
||||
*/
|
||||
public @NotNull Mono<ServicePool> recycle() {
|
||||
this.getAssociatedServices().clear();
|
||||
return Mono.just(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link Scheduler} which hosts the threads for the service pool.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public Scheduler getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
Reference in New Issue
Block a user