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

react-pipeline

v14.7.1

Published

A task execution pipeline described in JSX

Downloads

10

Readme

React Pipeline

A task execution pipeline described in JSX.

Build Status

Install

$ npm install --save react react-pipeline

Example

An example application can be found at react-pipeline-example.

Versions

React Pipeline uses semver and will match the versioning of React so developers know what version to install for their version of React. The exception is React Pipeline's major version will match React's minor version. At the time of this writing React is version 0.14.7, this would correspond to 14.7.0 in React Pipeline. When React releases version 15, they will be migrating their minor version to major, at which time React Pipeline will match the exactly.

Roadmap

  • Simplify internal API futher. This means that developers should rely on the two exported classes that React Pipeline makes available to be stable, but any internal classes that are not expored by index.js to be considered volatile.
  • Update to React v15
  • Utilize the render() method to output a visual representation of the pipeline. This could be used to generate administrative interfaces or to visualize the currently executing tasks.

Introduction

React Pipeline consists of two exported classes, Task and ReactPipeline.

Task is an example class wired with everything available for use within ReactPipeline including a standard render() method, an empty exec() method and a parallelTasks property.

The ReactPipeline class has one static method, start(), which starts all of the tasks. It is important to note that while the exec() method is asynchronous, ReactPipeline will default to running each of the child tasks in series. If a developer wants to run the tasks in parallel, the parental component must have a property parallelTasks set to true.

import ReactPipeline, { Task } from 'react-pipeline';

// Run tasks in series
ReactPipeline.start(
  <Task>
    <Task />
    <Task />
  </Task>
);

// Run tasks in parallel
ReactPipeline.start(
  <Task parallelTasks={true}>
    <Task />
    <Task />
  </Task>
);

The Task component is a standard React component configured to be used within React Pipeline. The pipeline can use any React component, but only components with an exec() method will be run during execution.

In order to implement your task's functionality you need only inherit from Task and override the exec() method. The exec() method must return a Promise.

import { Task } from 'react-pipeline';

export default class PauseTask extends Task {
  exec() {
    const duration = this.props.duration || 1000;

    return new Promise((resolve, reject) {
      setTimeout(resolve, duration);
    });
  }
}

If inheriting from Task and overriding render(), or starting from scratch with your own component and implementing render(), it is very important, if you are supporting child tasks, to ensure render() outputs it's this.props.children. If child tasks are not executing it is because your component is not rendering it's children.

class AwesomeClass {
  exec() {
    return Promise.resolve();
  }

  render() {
    return <div>{this.props.children}</div>
  }
}

Task objects can have any number of children and their tasks will run in series once the parent's task is complete. The exception to this rule is when setting the property parallelTasks to true, each of it's children's tasks will be run in parallel.

ReactPipeline.start(
  <Task>
    <CreateAWSServer>
      <Geocoding input={rawPath} output={geoPath} />
      <RunPig script={resolveScript} input={geoPath} output={resolvePath} />
      <RunPig script={joinScript} input={resolvePath} output={joinPath} />
      <RunSpark script={mlScript} input={joinPath} output={mlPath} />
      <Task parallelTasks={true}>
        <Upload input={joinPath} output={joinDestination} />
        <Upload input={mlPath} output={mlDestination} />
      </Task>
      <Email to={adminEmail} subject={subject} body="pipeline complete" />
    </CreateAWSServer>
  </Task>
);

In the example above the pipeline describes a series of (theoretical) tasks. The outcome of those tasks are as follows:

  • Create an AWS server and pass it's server context onto it's children (after v2 I would hope this information is passed down via properties instead)
  • Download city information from google and output the data to a location
  • Resolve the city location with the user profiles
  • Join the user profiles with a larger data set
  • Run a machine learning algorithm on the joined profile data
  • IN PARALLEL
    • Upload the profile data to a location
    • Upload the results of the machine learning to a location
  • Email the admin that the pipeline has completed

When creating a custom task it is possible to embed child tasks within it to create a reusable group of tasks. Using the above example we could combine the tasks into a reusable group.

class GroupTask extends Task {
  render() {
    return (
      <CreateAWSServer>
        <Geocoding input={rawPath} output={geoPath} />
        <RunPig script={resolveScript} input={geoPath} output={resolvePath} />
        <RunPig script={joinScript} input={resolvePath} output={joinPath} />
        <RunSpark script={mlScript} input={joinPath} output={mlPath} />
        <Task parallelTasks={true}>
          <Upload input={joinPath} output={joinDestination} />
          <Upload input={mlPath} output={mlDestination} />
        </Task>
        <Email to={adminEmail} subject={subject} body="pipeline complete" />
        {this.props.children}
      </CreateAWSServer>
    );
  }
}

ReactPipeline.start(
  <GroupTask>
    <LamdaTask />
  </GroupTask>
);

The above example combines the previous examples functionality into a reusable group, and allows for additional tasks to be added after all of it's tasks are complete.

Finally, when running tasks in series, it is possible to update the properties on uncompleted tasks by setting the state in the parent. This could be useful if you are planning on piping the result of one task to the next. This is only reliable when running tasks in series.

class ParentTask extends Task {
  state = {
    lastResult: null
  }

  handleComplete(result) {
    this.setState({ lastResult: result });
  }

  render() {
    return (
      <Task>
        <ReadFile onComplete={this.handleComplete.bind(this)} />
        <CountWords onComplete={this.handleComplete.bind(this)} lastResult={this.state.lastResult} />
        <Top10MostUsedWords onComplete={this.handleComplete.bind(this)} lastResult={this.state.lastResult} />
        <WriteFile onComplete={this.handleComplete.bind(this)} lastResult={this.state.lastResult} />
      </Task>
    )
  }
}

In the above example I illustrate how you could use hypothetical tasks, properties, and parental state to pipe the result of one task to the next. Here we read in a file, count the words, pick the top 10 most used words, then write those words out to a file.

Lifecycle Methods

Currently all lifecycle methods that are supported by ReactDOMServer are supported in React Pipeline, this includes getDefaultProps() and componentWillMount(). Along with these lifecycle methods two additional lifecycle methods have been added componentWillExec() and componentDidExec(). componentWillExec() gets called for each Task instance before it's exec() method is called or any of it's child tasks are started. componentDidExec() gets called for each Task instance after it's exec() method is called and after all of it's child tasks have completed.

Rationale

For the past four years I have worked primarily on big data projects utilizing various technologies like Hadoop, Pig, Hive, Spark, etc. An all of these projects I've needed to execute a number of tasks in order to reach my project goal. An example would be resolving a user profile's city via their postal code; join that data to a larger profile data set; wrangle the resolved data set into a structure I could use for analysis; then run some algorithms on that data for the final result. Each step in the pipeline may utilize a different technology; resolving cities from postal codes may require an application written in Python or Node to fetch information from Google's Geocoding API; joining and wrangling the data may utilize Pig on Hadoop; and the final analysis may utilize Spark.

In the past I have used Luigi, AWS Data Pipeline, and custom pipeline code to string these tasks together. On one fateful day I was working on a React project while some of my data analysis tasks were running when I realized that describing a pipeline using JSX and executing those tasks under React+Redux would be intuitive and would allow me to easily write tasks involving server code in Node.js. Thus React Pipeline was born.

License

React Pipeline is BSD licensed.