Skip to content
This repository has been archived by the owner on Jun 13, 2024. It is now read-only.

Commit

Permalink
Add an example that uses napa.sync.Lock (#179)
Browse files Browse the repository at this point in the history
* Add example for napa/sync/Lock

* Update link to sync.md

* Update example and rename to 'synchronized-loading'

* Update README and API docs: add synchronized loading example

* Resolve comments

* fix grammer
  • Loading branch information
fs-eire authored Jan 5, 2018
1 parent 0f699c5 commit f152547
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ zone1.execute(
```
More examples:
* [Estimate PI in parallel](./examples/tutorial/estimate-pi-in-parallel)
* [Max sub-matrix of 1s with layered parallelism](./examples/tutorial/max-square-sub-matrix)
* [Parallel Quick Sort](./examples/tutorial/parallel-quick-sort)
* [Recursive Fibonacci with multiple JavaScript threads](./examples/tutorial/recursive-fibonacci)
* [Max sub-matrix of 1s with layered parallelism](./examples/tutorial/max-square-sub-matrix)
* [Synchronized loading](./examples/tutorial/synchronized-loading)

## Features
- Multi-threaded JavaScript runtime
Expand Down
3 changes: 3 additions & 0 deletions docs/api/sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ catch(error) {
console.log(error);
}
```

An example [Synchronized Loading](./../../examples/tutorial/synchronized-loading) demonstrated how to implement a shared, lazy-loading phone book.

<!--
### <a name="lock-guard-func-promise-any-promise-any"></a> lock.guard(func: () => Promise\<any>): Promise\<any>
Expand Down
22 changes: 22 additions & 0 deletions examples/tutorial/synchronized-loading/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Synchronized loading
This example implements a shared phone book component. The component will not load data until the first lookup request happens. When it starts to load data, it ensures the loading will run only once.

The component is implemented using lazy-loading pattern with the use of [`napa.sync.Lock`](./../../../docs/api/sync.md#interface-lock).

## How to run
1. Go to directory of "examples/tutorial/synchronized-loading"
2. Run "npm install" to install napajs
3. Run "node synchronized-loading.js"

## Program output
The output below shows one possible result. The sequence of the output may be different but the data loading will always run once only.
```
[lookupPhoneNumber] Start to lookup phone number of david.
[lookupPhoneNumber] Start to lookup phone number of wade.
[load_data] loading...
[lookupPhoneNumber] Start to lookup phone number of lisa.
[lookupPhoneNumber] wade : <not found>.
[lookupPhoneNumber] lisa : 567-888-9999.
[lookupPhoneNumber] david : 123-444-5555.
[run] All operations are completed.
```
9 changes: 9 additions & 0 deletions examples/tutorial/synchronized-loading/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "napajs-tutorial",
"version": "0.1.0",
"author": "napajs",
"main": "./synchronized-loading.js",
"dependencies": {
"napajs": ">= 0.1.8"
}
}
6 changes: 6 additions & 0 deletions examples/tutorial/synchronized-loading/phone-book-data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"ashley": "123-456-7890",
"david": "123-444-5555",
"lisa": "567-888-9999",
"tony": "456-789-0000"
}
40 changes: 40 additions & 0 deletions examples/tutorial/synchronized-loading/phone-book.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

const napa = require("napajs");
const store = napa.store.getOrCreate('my-phone-book');

const initialize = function () {
store.set('_loadLock', napa.sync.createLock());
}

const load_data = function () {
// load data. This function should run only once.
console.log('[load_data] loading...');

const fs = require('fs');
let phoneBookData = JSON.parse(fs.readFileSync('./phone-book-data.json').toString());

for (let name in phoneBookData) {
store.set(name, phoneBookData[name]);
}
store.set('_loaded', true);
}

let loaded = false;
const lookup = function (name) {
if (!loaded) {
const lock = store.get('_loadLock');
lock.guardSync(function() {
if (!store.get('_loaded')) {
load_data();
}
});
loaded = true;
}

return store.get(name);
};

module.exports.initialize = initialize;
module.exports.lookup = lookup;
42 changes: 42 additions & 0 deletions examples/tutorial/synchronized-loading/synchronized-loading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

const napa = require("napajs");

// Change this value to control number of napa workers initialized.
const NUMBER_OF_WORKERS = 4;

// Create a napa zone with number_of_workers napa workers.
const zone = napa.zone.create('zone', { workers: NUMBER_OF_WORKERS });

function run() {
// Initialize the phone book component
const phoneBook = require('./phone-book');
phoneBook.initialize();

// Setup all workers with functions to be executed.
zone.broadcast(' \
var napa = require("napajs"); \
var zone = napa.zone.get("zone"); \
var phoneBook = require("./phone-book"); \
');
zone.broadcast(lookupPhoneNumber.toString());

var tasks = [];
tasks.push(zone.execute('', 'lookupPhoneNumber', ['david']));
tasks.push(zone.execute('', 'lookupPhoneNumber', ['lisa']));
tasks.push(zone.execute('', 'lookupPhoneNumber', ['wade']));

Promise.all(tasks).then(function () {
console.log('[run] All operations are completed.');
});
}

function lookupPhoneNumber(name) {
console.log(`[lookupPhoneNumber] Start to lookup phone number of ${name}.`);
var n = phoneBook.lookup(name);
console.log(`[lookupPhoneNumber] ${name} : ${n ? n : '<not found>'}.`);
}

// Run program.
run();

0 comments on commit f152547

Please sign in to comment.