Add an example that uses napa.sync.Lock (#179)

* 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
This commit is contained in:
Yulong Wang 2018-01-05 15:19:54 -08:00 коммит произвёл GitHub
Родитель 0f699c541b
Коммит f152547def
7 изменённых файлов: 124 добавлений и 1 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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>

Просмотреть файл

@ -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.
```

Просмотреть файл

@ -0,0 +1,9 @@
{
"name": "napajs-tutorial",
"version": "0.1.0",
"author": "napajs",
"main": "./synchronized-loading.js",
"dependencies": {
"napajs": ">= 0.1.8"
}
}

Просмотреть файл

@ -0,0 +1,6 @@
{
"ashley": "123-456-7890",
"david": "123-444-5555",
"lisa": "567-888-9999",
"tony": "456-789-0000"
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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();