Skip to content

Commit

Permalink
refactor: refactor and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
stawirej committed Dec 8, 2023
1 parent 927db82 commit 8ec2f25
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package pl.amazingcode.threadscollider.multi;

/** Builder for mandatory action. */
public interface MandatoryActionBuilder {

/**
* Set action to be executed.
*
* @param action action to be executed
* @return builder
*/
TimesBuilder withAction(Runnable action);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package pl.amazingcode.threadscollider.multi;

import java.util.function.Consumer;
import pl.amazingcode.threadscollider.single.OptionalBuilder;
import pl.amazingcode.threadscollider.single.ThreadsCollider;
import pl.amazingcode.threadscollider.single.TimeUnitBuilder;

/** Intermediary builder for {@link ThreadsCollider}. */
public interface MultiOptionalBuilder {

/**
* Sets exception consumer for threads. This consumer will be called for each exception thrown by
* threads. Consumer will be called in thread safe manner.
*
* @param threadsExceptionsConsumer - exception consumer for threads.
* @return {@link OptionalBuilder}
*/
MultiOptionalBuilder withThreadsExceptionsConsumer(Consumer<Exception> threadsExceptionsConsumer);

/**
* Sets await termination timeout for executor service used by {@link ThreadsCollider}.
*
* @param timeout - await termination timeout for executor service used by {@link
* ThreadsCollider}.
* @return {@link TimeUnitBuilder}
*/
MultiTimeUnitBuilder withAwaitTerminationTimeout(long timeout);

/**
* Builds {@link ThreadsCollider}.
*
* @return {@link ThreadsCollider}
*/
MultiThreadsCollider build();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.function.Consumer;
import pl.amazingcode.threadscollider.exceptions.ThreadsColliderFailure;

/** Allows to execute multiple actions by all threads at the "same time". */
public final class MultiThreadsCollider implements AutoCloseable {

private static final long DEFAULT_TIMEOUT = 60;
Expand Down Expand Up @@ -47,6 +48,12 @@ private MultiThreadsCollider(
this.threadsExceptionsConsumer = threadsExceptionsConsumer;
}

/**
* Tries to execute multiple actions by all threads at the "same time".
*
* @throws ThreadsColliderFailure if any exception occurs during execution. This not includes
* exceptions thrown by threads.
*/
public void collide() {

try {
Expand Down Expand Up @@ -90,6 +97,7 @@ private void decorate(Runnable runnable) {
}
}

/** Shuts down the executor service and waits for all threads to finish by given timeout. */
@Override
public void close() {
try {
Expand All @@ -107,7 +115,13 @@ private synchronized void consumeException(Exception exception) {
threadsExceptionsConsumer.accept(exception);
}

public static class MultiThreadsColliderBuilder {
/** Builder for {@link MultiThreadsCollider}. */
public static class MultiThreadsColliderBuilder
implements MandatoryActionBuilder,
OptionalActionBuilder,
TimesBuilder,
MultiTimeUnitBuilder,
MultiOptionalBuilder {

private final List<Runnable> runnables;
private final List<Integer> times;
Expand All @@ -121,78 +135,90 @@ private MultiThreadsColliderBuilder() {
this.times = new ArrayList<>();
}

public static MultiThreadsColliderBuilder multiThreadsCollider() {
public static MandatoryActionBuilder multiThreadsCollider() {

return new MultiThreadsColliderBuilder();
}

public MultiThreadsColliderBuilder withAction(Runnable runnable) {
@Override
public TimesBuilder withAction(Runnable runnable) {

this.runnables.add(runnable);
return this;
}

@Override
public MultiThreadsColliderBuilder times(int times) {

this.times.add(times);
return this;
}

public MultiThreadsColliderBuilder withAwaitTerminationTimeout(long timeout) {
@Override
public MultiTimeUnitBuilder withAwaitTerminationTimeout(long timeout) {

this.timeout = timeout;
return this;
}

public MultiThreadsColliderBuilder withThreadsExceptionsConsumer(
@Override
public MultiOptionalBuilder withThreadsExceptionsConsumer(
Consumer<Exception> threadsExceptionsConsumer) {

this.threadsExceptionsConsumer = threadsExceptionsConsumer;
return this;
}

public MultiThreadsColliderBuilder asNanoseconds() {
@Override
public MultiOptionalBuilder asNanoseconds() {

this.timeUnit = TimeUnit.NANOSECONDS;
return this;
}

@Override
public MultiThreadsColliderBuilder asMicroseconds() {

this.timeUnit = TimeUnit.MICROSECONDS;
return this;
}

@Override
public MultiThreadsColliderBuilder asMilliseconds() {

this.timeUnit = TimeUnit.MILLISECONDS;
return this;
}

@Override
public MultiThreadsColliderBuilder asSeconds() {

this.timeUnit = TimeUnit.SECONDS;
return this;
}

@Override
public MultiThreadsColliderBuilder asMinutes() {

this.timeUnit = TimeUnit.MINUTES;
return this;
}

@Override
public MultiThreadsColliderBuilder asHours() {

this.timeUnit = TimeUnit.HOURS;
return this;
}

@Override
public MultiThreadsColliderBuilder asDays() {

this.timeUnit = TimeUnit.DAYS;
return this;
}

@Override
public MultiThreadsCollider build() {

int threadsCount = times.stream().mapToInt(Integer::intValue).sum();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package pl.amazingcode.threadscollider.multi;

import pl.amazingcode.threadscollider.single.Builder;
import pl.amazingcode.threadscollider.single.ThreadsCollider;

/** Intermediary builder for {@link ThreadsCollider}. */
public interface MultiTimeUnitBuilder {

/**
* Sets await termination timeout time unit for executor service used by {@link ThreadsCollider}
* as nanoseconds.
*
* @return {@link Builder}
*/
MultiOptionalBuilder asNanoseconds();

/**
* Sets await termination timeout time unit for executor service used by {@link ThreadsCollider}
* as microseconds.
*
* @return {@link Builder}
*/
MultiOptionalBuilder asMicroseconds();

/**
* Sets await termination timeout time unit for executor service used by {@link ThreadsCollider}
* as milliseconds.
*
* @return {@link Builder}
*/
MultiOptionalBuilder asMilliseconds();

/**
* Sets await termination timeout time unit for executor service used by {@link ThreadsCollider}
* as seconds.
*
* @return {@link Builder}
*/
MultiOptionalBuilder asSeconds();

/**
* Sets await termination timeout time unit for executor service used by {@link ThreadsCollider}
* as minutes.
*
* @return {@link Builder}
*/
MultiOptionalBuilder asMinutes();

/**
* Sets await termination timeout time unit for executor service used by {@link ThreadsCollider}
* as hours.
*
* @return {@link Builder}
*/
MultiOptionalBuilder asHours();

/**
* Sets await termination timeout time unit for executor service used by {@link ThreadsCollider}
* as days.
*
* @return {@link Builder}
*/
MultiOptionalBuilder asDays();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pl.amazingcode.threadscollider.multi;

import java.util.function.Consumer;

public interface OptionalActionBuilder {

TimesBuilder withAction(Runnable action);

MultiTimeUnitBuilder withAwaitTerminationTimeout(long timeout);

MultiOptionalBuilder withThreadsExceptionsConsumer(Consumer<Exception> threadsExceptionsConsumer);

MultiThreadsCollider build();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package pl.amazingcode.threadscollider.multi;

public interface TimesBuilder {

OptionalActionBuilder times(int times);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package pl.amazingcode.threadscollider.architecture;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
final class Architecture_Scenarios {

private static final String ROOT_PACKAGE = "pl.amazingcode.threadscollider";
private static final String SINGLE_PACKAGE = "pl.amazingcode.threadscollider.single";
private static final String MULTI_PACKAGE = "pl.amazingcode.threadscollider.multi";

private final JavaClasses classes =
new ClassFileImporter()
.withImportOption(new ImportOption.DoNotIncludeTests())
.importPackages(ROOT_PACKAGE);

@Test
void Independent_single_package() {

noClasses()
.that()
.resideInAPackage(SINGLE_PACKAGE)
.should()
.dependOnClassesThat()
.resideInAnyPackage(MULTI_PACKAGE)
.check(classes);
}

@Test
void Independent_multi_package() {

noClasses()
.that()
.resideInAPackage(MULTI_PACKAGE)
.should()
.dependOnClassesThat()
.resideInAnyPackage(SINGLE_PACKAGE)
.check(classes);
}
}

0 comments on commit 8ec2f25

Please sign in to comment.