npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@rosen-bridge/service-manager

v0.1.2

Published

is a Typescript package to simplify auto-start and auto-stop service management in a hierarchical structure, ensuring proper startup order and dependency handling

Downloads

164

Readme

@rosen-bridge/service-manager

Table of contents

Introduction

@rosen-bridge/service-manager is a Typescript package to simplify auto-start and auto-stop service management in a hierarchical structure, ensuring proper startup order and dependency handling.

With this package, developers can streamline the process of managing services by automating the startup and shutdown procedures. It takes care of the complexities involved in handling dependencies between services, ensuring that they start in the correct order to avoid any conflicts or issues. By using this package, developers can focus on building their applications while relying on the service manager to handle the service lifecycle efficiently and effectively.

Installation

npm:

npm i @rosen-bridge/service-manager

yarn:

yarn add @rosen-bridge/service-manager

Implementation Details

Before diving into the implementation details, it is important to understand the concept of actions in this context. In this system, actions refer to the operations of starting and stopping a service. These actions are requested by various components and are stored in a Map data structure called pendingActions. This map keeps track of the requested actions for each service id.

Each action has some requirements which oversees service dependencies or dependants based on the action operation, i.e. "start" action requires service dependencies to be in appropriate state and "stop" requires service dependants to be stopped. For instance, if service A depends on service B, starting A requires service B to be in "running" state.

The concept of dependency entails a service requiring another service or services to be in the specified state and it's hardcoded into the service implementation. Additionally, each service has startService and stopService methods which are only called after all requirements of their action are satisfied.

Action

The process of starting and stopping services in this system follows a hierarchical structure. This means that the start and stop operations of services are performed in a cascading manner, where starting a service triggers the start of its dependent services, and stopping a service also stops its dependants. Service manager checks and behaviors includes:

  • Pending Action Check:

    • Before any action is initiated, a check is performed to determine if there are any pending actions for the corresponding service in the pendingActions map.
    • If no pending action is found for the service, the new action is added to the action map.
    • The action requirements are then examined and the necessary steps are taken to ensure they are satisfied.
    • Only when all requirements are met, the action is executed for the service.
  • Action Collision Handling:

    • If there is already a different pending action for the same service in the pendingActions map, an appropriate error is returned to prevent a potential action collision.
  • Dependency Resolution:

    • If the same action is already present in the pendingActions, the dependencies are re-evaluated.
    • If all dependencies are in the appropriate state, the action proceeds.
    • If some dependencies are still not ready, the promise of current pending action for this service which is stored in the pendingPromises, is returned.
  • Dependency Handling:

    • Dependencies are handled through action requirements.
    • For instance, if Service B depends on Service C and Service M, the status of these two services is checked for the "start" operation.
    • If either Service C or Service M is not in the "running" state, the "start" operation for Service B is held off until both reach the specified state.
    • Conversely, when both Service C and Service M reach the appropriate states, the startService method is invoked for Service B.
    • Similarly, for the "stop" operation, stopping Service M necessitates stopping Service B first, which in turn requires stopping Service A beforehand. This sequential dependency ensures a proper shutdown sequence.

By overseeing the functionalities described above, we ensure that the system starts and stops services in a controlled and cascading manner, taking into account their dependencies and maintaining the integrity of the system.

Service Status Change

ServiceManager works not only by performing actions, but also by changes in service statuses. When a service undergoes a status change, the ServiceManager becomes aware of it through the callbackHandler function. In such cases, depending on the next status, the following actions should take place:

  • If the next status is "started" or "running," the dependants of the service need to be examined. If they have a pending "start" operation in the pendingActions map and all their dependencies are ready, the operation is executed along with resolving or rejecting the pending action.

  • If the next status is "dormant," all dependants of the service must be stopped. Additionally, all dependencies of the service should be checked, and if there are pending "stop" operations in the pendingActions map and their requirements are satisfied, stopService is invoked. It is important to note that the responsibility of managing a service that is already stopped and should not be stopped again lies with the AbstractService itself.

By implementing these actions based on the service status change, we ensure that the dependents are appropriately handled and that the system maintains the desired state and behavior.

Usage

First you need to define your services while inheriting AbstractService class. Don't forget to define dependencies. In this example, service X1A depends on X1B.

import { AbstractService } from '@rosen-chains/service-manager';

class X1A extends AbstractService {
  name = 'X1A';

  protected dependencies: Dependency[] = [
    {
      serviceName: 'X1B',
      allowedStatuses: [ServiceStatus.running],
    },
  ];

  // implement other required functions
  // ...
}

class X1B extends AbstractService {
  name = 'X1B';

  protected dependencies: Dependency[] = [];

  // implement other required functions
  // ...
}

Then initialize ServiceManager instance and register your services.

import { ServiceManager } from '@rosen-chains/service-manager';

const serviceManager = ServiceManager.setup();
const serviceX1A = new X1A();
serviceManager.register(serviceX1A);
const serviceX1B = new X1B();
serviceManager.register(serviceX1B);

Then you can start and stop services using service manager.

serviceManager.start(serviceX1A.getName());
serviceManager.stop(serviceX1A.getName());