Skip to content

Commit ee8079e

Browse files
committed
Update package version to include queue lifespan functionality and updated README with OS background task example.
1 parent fab3797 commit ee8079e

File tree

2 files changed

+167
-10
lines changed

2 files changed

+167
-10
lines changed

README.md

Lines changed: 166 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
[![JSDoc](https://img.shields.io/badge/jsdoc-100%25%20code%20documentation-green.svg)](http://usejsdoc.org/)
88
[![Coverage Status](https://coveralls.io/repos/github/billmalarky/react-native-queue/badge.svg?branch=master)](https://coveralls.io/github/billmalarky/react-native-queue?branch=master)
99

10-
A React Native job queue / task queue backed by persistent Realm storage. Jobs will persist until completed, even if user closes and re-opens app. React Native Queue is easily integrated into React Native background processes so you can ensure the queue will continue to process until all jobs are completed.
10+
A React Native at-least-once priority job queue / task queue backed by persistent Realm storage. Jobs will persist until completed, even if user closes and re-opens app. React Native Queue is easily integrated into OS background processes so you can ensure the queue will continue to process until all jobs are completed even if app isn't in focus.
1111

12-
##Features
12+
## Features
1313

1414
* **Simple API:** Set up job workers and begin creating your jobs in minutes with just two basic API calls
1515
* queue.addWorker(name, workerFunction, options = {})
1616
* queue.createJob(name, payload = {}, options = {}, startQueue = true)
17-
* **Powerful options:** Easily modify default functionality. Set job timeouts, number of retry attempts, priority, and worker concurrency with an options object.
17+
* **Powerful options:** Easily modify default functionality. Set job timeouts, number of retry attempts, priority, and worker concurrency with an options object. Start queue processing with a lifespan to easily meet OS background task time limits.
1818
* **Persistent Jobs:** Jobs are persisted with Realm. Because jobs persist, you can easily continue to process jobs across app restarts or in OS background tasks until completed or failed (or app is uninstalled).
1919

20-
##Installation
20+
## Installation
2121

2222
```bash
2323
$ npm install --save react-native-queue
@@ -39,16 +39,16 @@ Linking realm **should only be done once**, reinstalling node_modules with npm o
3939

4040
To troubleshoot linking, refer to [the realm installation instructions](https://realm.io/docs/javascript/latest/#getting-started).
4141

42-
##Basic Usage
42+
## Basic Usage
4343

4444
React Native Queue is a standard job/task queue built specifically for react native applications. If you have a long-running task, or a large number of tasks, consider turning that task into a job(s) and throwing it/them onto the queue to be processed in the background instead of blocking your UI until task(s) complete.
4545

4646
Creating and processing jobs consists of:
4747

48-
1. Importing React Native Queue
48+
1. Importing and initializing React Native Queue
4949
2. Registering worker functions (the functions that execute your jobs).
5050
3. Creating jobs.
51-
4. Starting the queue (note this happens automatically on job creation, but sometimes the queue must be explicitly started such as in a OS background task or on app restart).
51+
4. Starting the queue (note this happens automatically on job creation, but sometimes the queue must be explicitly started such as in a OS background task or on app restart). Queue can be started with a lifespan in order to limit queue processing time.
5252

5353
```js
5454

@@ -108,11 +108,11 @@ queue.createJob('example-job', {
108108
}
109109
});
110110

111-
console.log('The above jobs are processing in the background now.');
111+
console.log('The above jobs are processing in the background of app now.');
112112

113113
```
114114

115-
##Options
115+
## Options
116116

117117
**Worker Options**
118118

@@ -354,3 +354,160 @@ const styles = StyleSheet.create({
354354

355355

356356
```
357+
358+
**OS Background Task Full Example**
359+
360+
For the purpose of this example we will use the [React Native Background Task](https://github.com/jamesisaac/react-native-background-task) module, but you could integrate React Native Queue with any acceptable OS background task module.
361+
362+
Follow the [installation steps](https://github.com/jamesisaac/react-native-background-task#installation) for React Native Background Task.
363+
364+
```js
365+
366+
import React, { Component } from 'react';
367+
import {
368+
Platform,
369+
StyleSheet,
370+
Text,
371+
View,
372+
Button,
373+
AsyncStorage
374+
} from 'react-native';
375+
376+
import BackgroundTask from 'react-native-background-task'
377+
import queueFactory from 'react-native-queue';
378+
379+
BackgroundTask.define(async () => {
380+
381+
// Init queue
382+
queue = await queueFactory();
383+
384+
// Register worker
385+
queue.addWorker('background-example', async (id, payload) => {
386+
387+
const personId = (payload.name == 'luke') ? 1 : 2;
388+
389+
// Let's make a request for some data in the background and store it to AsyncStorage.
390+
// This data would be available from AsyncStorage the next time your user fires up the app!
391+
const response = await fetch('https://swapi.co/api/people/' + personId + '/');
392+
const text = await response.text();
393+
394+
if (payload.name == 'luke') {
395+
await AsyncStorage.setItem('lukeData', text);
396+
} else {
397+
await AsyncStorage.setItem('c3poData', text);
398+
}
399+
400+
});
401+
402+
// Start the queue with a lifespan
403+
// IMPORTANT: OS background tasks are limited to 30 seconds or less.
404+
// NOTE: Queue lifespan logic will attempt to stop queue processing 500ms less than passed lifespan for a healthy shutdown buffer.
405+
// IMPORTANT: Queue processing started with a lifespan will ONLY process jobs that have a defined timeout set.
406+
// Additionally, lifespan processing will only process next job if job.timeout < (remainingLifespan - 500).
407+
await queue.start(20000); // Run queue for at most 20 seconds.
408+
409+
// finish() must be called before OS hits timeout.
410+
BackgroundTask.finish();
411+
412+
});
413+
414+
export default class App extends Component<{}> {
415+
416+
constructor(props) {
417+
super(props);
418+
419+
this.state = {
420+
queue: null,
421+
data: null
422+
};
423+
424+
this.init();
425+
426+
}
427+
428+
async init() {
429+
430+
const queue = await queueFactory();
431+
432+
// Add the worker.
433+
queue.addWorker('background-example', async (id, payload) => {
434+
// Worker has to be defined before related jobs can be added to queue.
435+
// Since this example is only concerned with OS background task worker execution,
436+
// We will make this a dummy function in this context.
437+
console.log(id);
438+
});
439+
440+
// Attach initialized queue to state.
441+
this.setState({
442+
queue
443+
});
444+
445+
}
446+
447+
componentDidMount() {
448+
BackgroundTask.schedule(); // Schedule the task to run every ~15 min if app is closed.
449+
}
450+
451+
makeJob(jobName, payload = {}) {
452+
console.log('job is created but will not execute until the above OS background task runs in ~15 min');
453+
this.state.queue.createJob(jobName, payload, {
454+
455+
timeout: 5000 // IMPORTANT: If queue processing is started with a lifespan ie queue.start(lifespan) it will ONLY process jobs with a defined timeout.
456+
457+
}, false); // Pass false so queue doesn't get started here (we want the queue to start only in OS background task in this example).
458+
}
459+
460+
async checkData() {
461+
462+
const lukeData = await AsyncStorage.getItem('lukeData');
463+
const c3poData = await AsyncStorage.getItem('c3poData');
464+
465+
this.setState({
466+
data: {
467+
lukeData: (lukeData) ? lukeData : 'No data loaded from OS background task yet for Luke Skywalker.',
468+
c3poData: (c3poData) ? c3poData : 'No data loaded from OS background task yet for C-3PO.'
469+
}
470+
});
471+
472+
}
473+
474+
render() {
475+
476+
let output = 'No data loaded from OS background task yet.';
477+
if (this.state.data) {
478+
output = JSON.stringify(this.state.data);
479+
}
480+
481+
return (
482+
<View style={styles.container}>
483+
<Text style={styles.welcome}>
484+
Welcome to React Native!
485+
</Text>
486+
<Text>Click buttons below to add OS background task jobs.</Text>
487+
<Text>Then Close App (task will not fire if app is in focus).</Text>
488+
<Text>Job will exec in ~15 min in OS background.</Text>
489+
{this.state.queue && <Button title={"Press To Queue Luke Skywalker Job"} onPress={ () => { this.makeJob('background-example', { name: 'luke' }) } } /> }
490+
{this.state.queue && <Button title={"Press To Queue C-3PO Job"} onPress={ () => { this.makeJob('background-example', { name: 'c3po' }) } } /> }
491+
<Button title={"Check if Data was loaded in OS background"} onPress={ () => { this.checkData() } } />
492+
<Text>{output}</Text>
493+
</View>
494+
);
495+
496+
}
497+
}
498+
499+
const styles = StyleSheet.create({
500+
container: {
501+
flex: 1,
502+
justifyContent: 'center',
503+
alignItems: 'center',
504+
backgroundColor: '#F5FCFF',
505+
},
506+
welcome: {
507+
fontSize: 20,
508+
textAlign: 'center',
509+
margin: 10,
510+
},
511+
});
512+
513+
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-queue",
3-
"version": "1.0.0-alpha.1",
3+
"version": "1.0.0-alpha.2",
44
"description": "A React Native Job Queue",
55
"main": "index.js",
66
"scripts": {

0 commit comments

Comments
 (0)