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

@jcachay/command-queue

v3.1.3

Published

Angular library that adds commands to a queue so they can be processed at the server speed while updating a local copy of the view model automatically

Downloads

9

Readme

Developer notes

Overview

The client adds commands, that are executed one after the other in a queue. The response from each command can be send back with the next command, for example, for optimistic concurrency.

  • A command must extend CommandQueueCommand class.

  • The client must provides services thru DI:

    • CommandQueueDataManagerService: knows how to call the server to execute the commands.
    • CommandQueueViewModelReaderService: knows how to get the data from the server (read)
    • CommandQueueUpdateViewModelFunctionFactoryService: Creates a function that knows how to update a local copy of the ViewModel to reflect the changes after each command.
  • The client must provide a ViewModel that extends CommandQueueViewModel

  • Add all the parts to the DI container

providers: [
    {provide: CommandQueueDataService, useClass: PetsDataService},
    {provide: CommandQueueUpdateViewModelFunctionFactoryService, 
    useClass: UpdateViewModelFunctionFactoryService},
    {provide: CommandQueueViewModelReaderService, useClass: ViewModelReaderService},
    {provide: CommandQueueDataService, useClass: PetsDataService},
    commandQueueDataManagerProvider,
    {provide: DeveloperNotificationsService}
  ]

Basic Usage

Initialize

Inject the data manager:

 constructor(private commandQueueDataManager : CommandQueueDataManagerService) { }

Before anything, the command manager must:

  • Read the ViewModel
  • Subscribe to notifications as in the following example
ngOnInit(): void {
    this.dm.readViewModel().subscribe();
    
    this.subscriptions.add(
      this.dm.onWriteErrorOccurred.subscribe(error=>{
        if (error instanceof ConcurrencyVersionMismatchError)
        {
          this.developerNotifications.notify("Concurrency version mismatch. The local model version did not " +
          "match the remote version. Data will be reloaded", true);
        }
      })
    );
  }

Add commands to the queue

const cmd = new AddPetCommand(uuid(), this.inputValue);
      this.dm.executeCommand(cmd);

The DataManager view model is updated after each command, using the UpdateViewModelFactory service. This allows the local ViewModel to reflect the server changes without having to wait for it. If an error occurs, the remaining commands in the queue are cancelled and the ViewModel reloaded.

Inner workings

Reader

See IDmReader interface. Provides mechanisms to read data, get the current version (the server response from the last command) and some notifications.

Its implementation DmReader (class), depends on the ViewModelReaderService (provided by the user via DI)

Writer

See IDmWriter interface. Provides mechanisms to write data (execute commands).

This method adds the commands to the queue:

executeCommand(cmd : CommandQueueCommand):void;

Read the interface to understand the other members.

Its implementation DmWriter depends on 3 services:

  • QueueFactory
  • ExecuteCommandFunctionFactory
  • IDmMediator

See the DmWritter code to understand how it delegates to these 3 services.

QueueFactory

Creates a queue

The factory code is very simple:

create():Queue
  {
    return new Queue(this.logger);
  }

What matters here is the Queue implementation.

The Queue is a class that allows adding a function (IExecuteCommandFunction) with an onErrorCallback. If the function throws an error, the callback is invoked. Otherwise, the next function in the queue is executed.

It also provides some properties, for example, to get how many commands are in the queue.

And a cancelAll method.

To understand this class see the Queue class

ExecuteCommandFunctionFactory

Receives a command and returns a function. When this function is invoked, the command is executed in the server.

See IExecuteCommandFunctionFactory interface.

Then, see its implementation ExecuteCommandFunctionFactory

This have 3 dependencies:

  • IDmMediator
  • CommandQueueUpdateViewModelFunctionFactoryService
  • CommandQueueDataService

The IDmMediator is the same as the one injected to the writer, explained later.

The ...FunctionFactoryService is the service provided by the user. It knows how to create a function that, when called, can update the ViewModel to reflect the changes as per the command.

The CommandQueueDataService is the DataService provided by the user.

See the code in the ExecuteCommandFunctionFactory

IDmMediator

Mediates between the Reader and the Writer

This is a very straight forward type. There are cases when the writter and the reader must communicate, this is the class thru which they communicate.

For example, in the DmWriter executeCommand method,

 executeCommand(cmd: CommandQueueCommand): void {
    let fn = this.executeCommandFunctionFactory
      .create(cmd);
    this._queue?.add(fn,(e)=>{
      this._queue.cancelAll();
      this._queue = this.queueFactory.create();
      this.mediator.read();
      this._writeErrorOccurred.next(e);
    });
  }

When an error occurs, the writer cancels all the commands in the queue and reads the view-model again. The read part must be delegated to the DMReader via the Mediator.