All files / src/impl ConcurrencyWrapper.impl.ts

83.33% Statements 20/24
100% Branches 0/0
83.33% Functions 10/12
83.33% Lines 20/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85  12x                       12x 260x                         260x                   222x 222x 222x 222x 205x 205x   205x                   18x       1x       69x       19x       18x               260x 260x     260x 260x  
import { Completable, CompletableConfig, Concurrency, OnCompletion, StateMachine, StateMachineConfig, Waitable, WaitableConfig } from "@jonloucks/concurrency-ts/api/Concurrency";
import { AutoClose, inlineAutoClose } from "@jonloucks/contracts-ts/api/AutoClose";
import { Repository } from "@jonloucks/contracts-ts/api/Repository";
import { ConsumerType, OptionalType, RequiredType, SupplierType } from "@jonloucks/concurrency-ts/api/Types";
 
/**
 * Wrapper method to create a Concurrency wrapper which is responsible for managing
 * the lifecycle of the underlying Repository and Concurrency instances.
 * 
 * @param concurrency the underlying Concurrency instance
 * @param repository the underlying Repository instance
 * @returns the Concurrency implementation
 */
export function wrap(concurrency: RequiredType<Concurrency>, repository: RequiredType<Repository>): Concurrency {
  return ConcurrencyWrapper.internalCreate(concurrency, repository);
}
 
// ---- Implementation details below ----
 
/**
 * The Concurrency wrapper implementation
 * Concurrency wrapper which is responsible for managing
 * the lifecycle of the underlying Repository and Concurrency instances.
 */
class ConcurrencyWrapper implements Concurrency {
 
  static internalCreate(concurrency: RequiredType<Concurrency>, repository: RequiredType<Repository>): Concurrency {
    return new ConcurrencyWrapper(concurrency, repository);
  }
 
  autoOpen(): AutoClose {
    // what if referrent also has autoOpen?
    // maybe we detect that and chain them?
    return this.open();
  }
 
  open(): AutoClose {
    const closeRepository: AutoClose = this.#repository.open();
    try {
      const closeConcurrency: AutoClose = this.#concurrency.open();
      return inlineAutoClose(() => {
        try {
          closeConcurrency.close(); 
        } finally {
          closeRepository.close(); // ensure repository is closed
        }
      });
    } catch (thrown) {
      closeRepository.close();
      throw thrown
    }
  }
 
  createWaitable<T>(config: WaitableConfig<T>): RequiredType<Waitable<T>> {
    return this.#concurrency.createWaitable(config);
  }
 
  createStateMachine<T>(config: StateMachineConfig<T>): RequiredType<StateMachine<T>> {
    return this.#concurrency.createStateMachine(config);
  }
 
  createCompletable<T>(config: CompletableConfig<T>): RequiredType<Completable<T>> {
    return this.#concurrency.createCompletable(config);
  }
 
  completeLater<T>(onCompletion: RequiredType<OnCompletion<T>>, delegate: RequiredType<ConsumerType<OnCompletion<T>>>): void {
    return this.#concurrency.completeLater(onCompletion, delegate);
  }
 
  completeNow<T>(onCompletion: RequiredType<OnCompletion<T>>, successBlock: RequiredType<SupplierType<T>>): OptionalType<T> {
    return this.#concurrency.completeNow(onCompletion, successBlock);
  }
 
  toString(): string {
    return this.#concurrency.toString();
  }
 
  private constructor(concurrency: RequiredType<Concurrency>, repository: RequiredType<Repository>) {
    this.#concurrency = concurrency;
    this.#repository = repository;
  }
 
  readonly #concurrency: RequiredType<Concurrency>;
  readonly #repository: RequiredType<Repository>;
};