зеркало из https://github.com/microsoft/napajs.git
Merged PR 293286: Documentation iteration 2
1. add metric.md and log.md 2. fix anchor issue in VSTS on displaying markdown format. 3. remove some legacy md files.
This commit is contained in:
Родитель
a641034ecc
Коммит
f41cb059be
18
README.md
18
README.md
|
@ -20,6 +20,12 @@ zone.execute(
|
|||
console.log(result.value);
|
||||
});
|
||||
```
|
||||
## Features
|
||||
- Multi-threaded JavaScript runtime
|
||||
- Node.JS compatible module architecture with NPM support
|
||||
- API for object transportation, object sharing and synchronization across JavaScript threads
|
||||
- API for pluggable logging, metric and memory allocator
|
||||
- Distributed as a Node.JS module, as well as supporting embed scenarios
|
||||
|
||||
## Architecture
|
||||
In Napa.JS, all works related to multi-threading are around the concept of `Zone`,
|
||||
|
@ -34,20 +40,10 @@ Workers across different zones are asymmetrical: they may load different code, o
|
|||
|
||||
Napa.JS provides API to access current or other zones in JavaScript, thus a parallelizable workflow can be easily described by `zone.execute` across workers or zones. Node.JS event loop is exposed as a single-worker 'virtual' zone. Thus code running in Napa.JS isolates can call to Node.JS world via `zone.node.execute`.
|
||||
|
||||
## Features
|
||||
- Multi-threaded JavaScript execution
|
||||
- Node.JS compatible module architecture with NPM support
|
||||
- JavaScript API for synchronization across JavaScript threads
|
||||
- JavaScript API for object transportation and sharing across JavaScript threads
|
||||
- C++ API for customizable memory allocation for native objects
|
||||
- C++ API for pluggable logging and metrics
|
||||
- C/C++ API for embedders
|
||||
|
||||
## Documentation
|
||||
- [API reference](docs/api/index.md)
|
||||
- [Benchmarks](benchmark/README.md)
|
||||
- [Embedder's guide](docs/embedder/index.md)
|
||||
- [Examples](docs/examples/index.md)
|
||||
- [Benchmarks](docs/benchmarks/index.md)
|
||||
- [Design docs](docs/design/index.md)
|
||||
|
||||
## Contribute
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
# API References
|
||||
|
||||
## Napa.JS APIs
|
||||
- [zone](./zone.md): Multi-thread JavaScript runtime
|
||||
- [transport](./transport.md): Transporting objects between JavaScript threads
|
||||
- [memory](./memory.md): Handling native objects and memories.
|
||||
- [sync](./sync.md): Synchronization between JavaScript threads
|
||||
## Core modules
|
||||
- namespace [`zone`](./zone.md): Multi-thread JavaScript runtime
|
||||
- namespace [`transport`](./transport.md): Passing objects across JavaScript threads
|
||||
- namespace [`store`](./store.md): Sharing objects across JavaScript threads
|
||||
- namespace [`sync`](./sync.md): Synchronization across JavaScript threads
|
||||
- namespace [`memory`](./memory.md): Handling native objects and memories
|
||||
- namespace [`metric`](./metric.md): API for pluggable metrics.
|
||||
- function [`log`](./log.md): API for pluggable logging.
|
||||
|
||||
- [module](./module.md): Writing Napa.JS modules
|
||||
## Node.JS compatibility
|
||||
- [List of supported Node APIs](./node-api.md)
|
||||
|
||||
## Supported Node.JS APIs
|
||||
- [List of supported Node APIs](./node.md)
|
||||
## API for module developers
|
||||
- [Writing Napa.JS modules](./module.md):
|
|
@ -0,0 +1,98 @@
|
|||
# function `log`
|
||||
|
||||
## Table of Contents
|
||||
- [Logging basics](#logging-basics)
|
||||
- [C++ API](#c-api)
|
||||
- [JavaScript API](#javascript-api)
|
||||
- [`log(message: string): void`](#log-message-string-void)
|
||||
- [`log(section: string, message: string): void`](#log-section-string-message-string-void)
|
||||
- [`log(section: string, traceId: string, message: string): void`](#log-section-string-traceid-string-message-string-void)
|
||||
- [`log.err(...)`](#log-error)
|
||||
- [`log.warn(...)`](#log-warn)
|
||||
- [`log.info(...)`](#log-info)
|
||||
- [`log.debug(...)`](#log-debug)
|
||||
- [Using custom logging providers](#using-custom-logging-providers)
|
||||
- [Developing custom logging providers](#developing-custom-logging-providers)
|
||||
|
||||
## Logging basics
|
||||
Logging is a basic requirement for building services. `napajs` logging API enables developers to integrate their own logging capabilities in both JavaScript and C++ (addon) world.
|
||||
|
||||
A log row may contain following information:
|
||||
- (Optional) Section: Useful as filter to treat different rows of logs. The treatment is defined by logging providers.
|
||||
- (Optional) Trace ID: Useful field to join logs in the same transaction or request.
|
||||
- (Required) Message: Log message.
|
||||
- (Required) Logging level:
|
||||
- Error: for application error.
|
||||
- Warn: for warining information.
|
||||
- Info: usually used for notifying service state change
|
||||
- Debug: for debugging purpose
|
||||
|
||||
## C++ API
|
||||
Include header: `<napa-log.h>`
|
||||
|
||||
Macros:
|
||||
- LOG_ERROR(section, format, ...)
|
||||
- LOG_ERROR_WITH_TRACEID(section, traceId, format, ...)
|
||||
- LOG_WARNING(section, format, ...)
|
||||
- LOG_WARNING_WITH_TRACEID(section, traceId, format, ...)
|
||||
- LOG_INFO(section, format, ...)
|
||||
- LOG_INFO_WITH_TRACEID(section, traceId, format, ...)
|
||||
- LOG_DEBUG(section, format, ...)
|
||||
- LOG_DEBUG_WITH_TRACEID(section, traceId, format, ...)
|
||||
|
||||
```cpp
|
||||
#include <napa-log.h>
|
||||
|
||||
void MyFunction() {
|
||||
// ...
|
||||
LOG_ERROR("init", "error: %s", errorMessage.c_str());
|
||||
}
|
||||
```
|
||||
|
||||
## JavaScript API
|
||||
|
||||
### log(message: string): void
|
||||
It logs a message. Using info level.
|
||||
*Functions `log` are shortcuts for `log.info`.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
import * as napa from 'napajs';
|
||||
napa.log('program started');
|
||||
```
|
||||
|
||||
### log(section: string, message: string): void
|
||||
It logs a message with a section. Using info level.
|
||||
Example:
|
||||
```ts
|
||||
napa.log('init', 'program started');
|
||||
```
|
||||
|
||||
### log(section: string, traceId: string, message: string): void
|
||||
It logs a message with a section, associating it with a traceId. Using info level.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
napa.log('request', 'A1B2C3D4', 'request received');
|
||||
```
|
||||
### log.err(...)
|
||||
It logs an error message. Three combinations of arguments are the same with `log`.
|
||||
|
||||
### log.warn(...)
|
||||
It logs a warning message. Three combinations of arguments are the same with `log`.
|
||||
|
||||
### log.info(...)
|
||||
It logs an info message. Three combinations of arguments are the same with `log`.
|
||||
|
||||
### log.debug(...)
|
||||
It logs a debug message. Three combinations of arguments are the same with `log`.
|
||||
|
||||
## Using custom logging providers
|
||||
Developers can hook up custom logging provider by calling the following before creation of any zones:
|
||||
```ts
|
||||
napa.runtime.setPlatformSettings({
|
||||
"loggingProvider": "<custom-logging-provider-module-name>"
|
||||
}
|
||||
```
|
||||
## Developing custom logging providers
|
||||
TBD
|
|
@ -1,55 +1,58 @@
|
|||
# namespace `memory`
|
||||
|
||||
## Table of Contents
|
||||
- type [`Handle`](#handle)
|
||||
- class [`Buffer`](#buffer)
|
||||
- interface [`Shareable`](#shareable)
|
||||
- interface [`Allocator`](#allocator)
|
||||
- [`allocator.allocate(size: number): Handle`](#allocator-allocate)
|
||||
- [`allocator.deallocate(handle: Handle, sizeHint: number): void`](#allocator-deallocate)
|
||||
- [`allocator.type: string`](#allocator-type)
|
||||
- interface [`AllocatorDebugger`](#allocatorDebugger)
|
||||
- [`allocatorDebugger.debugInfo: string`](#allocatorDebugger-debugInfo)
|
||||
- [`debugAllocator(allocator: Allocator): AllocatorDebugger`]
|
||||
- object [`crtAllocator`](#crtAllocator)
|
||||
- object [`defaultAllocator`](#defaultAllocator)
|
||||
- [Memory allocation in C++ addon](#memory-allocation)
|
||||
- type [`Handle`](#type-handle)
|
||||
- class [`Buffer`](#class-buffer)
|
||||
- interface [`Shareable`](#interface-shareable)
|
||||
- interface [`Allocator`](#interface allocator)
|
||||
- [`allocator.allocate(size: number): Handle`](#allocator-allocate-size-number-handle)
|
||||
- [`allocator.deallocate(handle: Handle, sizeHint: number): void`](#allocator-deallocate-handle-handle-sizehint-number-void)
|
||||
- [`allocator.type: string`](#allocator-type-string)
|
||||
- interface [`AllocatorDebugger`](#interface-allocatordebugger)
|
||||
- [`allocatorDebugger.debugInfo: string`](#allocatordebugger-debugInfo-string)
|
||||
- function [`debugAllocator(allocator: Allocator): AllocatorDebugger`](#debugallocator-allocator-allocator-allocatordebugger)
|
||||
- object [`crtAllocator`](#object-crtallocator)
|
||||
- object [`defaultAllocator`](#object-defaultallocator)
|
||||
- [Memory allocation in C++ addon](#memory-allocation-in-c-addon)
|
||||
|
||||
## APIs
|
||||
## <a name="handle"></a>Type `Handle`
|
||||
## Type `Handle`
|
||||
Handle is defined in TypeScript as below:
|
||||
```ts
|
||||
type Handle = [number, number]
|
||||
```
|
||||
It is a standard way to represent a 64-bit pointer in Napa.
|
||||
|
||||
## <a name="buffer"></a>Class `Buffer`
|
||||
## Class `Buffer`
|
||||
TBD
|
||||
## <a name="allocator"></a>Interface `Allocator`
|
||||
|
||||
## Interface `Shareable`
|
||||
Interface for native object wrap that can be shared across multiple JavaScript threads.
|
||||
|
||||
## Interface `Allocator`
|
||||
Interface for memory allocator that allocates memory for native objects.
|
||||
|
||||
### <a name="allocator-allocate"></a>allocator.allocate(size: number): Handle
|
||||
### allocator.allocate(size: number): Handle
|
||||
It allocates memory of requested size.
|
||||
|
||||
```ts
|
||||
let handle = allocator.allocate(10);
|
||||
```
|
||||
### <a name="allocator-deallocate"></a>allocator.deallocate(handle: Handle, sizeHint: number): void
|
||||
### allocator.deallocate(handle: Handle, sizeHint: number): void
|
||||
It deallocates memory from a input handle, with a size hint which is helpful for some C++ allocator implementations for deallocating memory.
|
||||
```ts
|
||||
allocator.deallocate(handle, 10);
|
||||
```
|
||||
### <a name="allocator-type"></a>allocator.type: string
|
||||
### allocator.type: string
|
||||
It gets a string type identifier for the allocator, which will be useful during debugging purpose.
|
||||
|
||||
|
||||
## <a name="allocatorDebugger"></a>Interface `AllocatorDebugger`
|
||||
## Interface `AllocatorDebugger`
|
||||
`AllocatorDebugger` extends interface `Allocator`, with a readonly property `debugInfo` to expose debug information. Basically an allocator debugger will use a pass-in allocator for memory allocation, meanwhile intercepting it to keep track of allocation count and size.
|
||||
|
||||
### <a name="allocatorDebugger-debugInfo"></a>allocatorDebugger.debugInfo: string
|
||||
### allocatorDebugger.debugInfo: string
|
||||
It gets the debug information for allocation.
|
||||
|
||||
## <a name="debugAllocator"></a>debugAllocator(allocator: Allocator): AllocatorDebugger
|
||||
## debugAllocator(allocator: Allocator): AllocatorDebugger
|
||||
It returns a simple allocator debugger, which returns debug information like below:
|
||||
```json
|
||||
{
|
||||
|
@ -59,19 +62,20 @@ It returns a simple allocator debugger, which returns debug information like bel
|
|||
"deallocateSize": 912
|
||||
}
|
||||
```
|
||||
## <a name="crtAllocator"></a>Object `crtAllocator`
|
||||
## Object `crtAllocator`
|
||||
It returns a C-runtime allocator from napa.dll. Its corresponding C++ part is `napa::memory::GetCrtAllocator()`.
|
||||
|
||||
## <a name="defaultAllocator"></a>Object `defaultAllocator`
|
||||
## Object `defaultAllocator`
|
||||
It returns the default allocator from napa.dll. Its corresponding C++ part is `napa::memory::GetDefaultAllocator()`. Users can set default allocation/deallocation callback in `napa_allocator_set` API.
|
||||
|
||||
## <a name="memory-allocation"></a>Memory allocation in C++ addon
|
||||
## Memory allocation in C++ addon
|
||||
Memory allocation in C++ addon is tricky. A common pitfall is to allocate memory in one dll, but deallocate in another. This can cause issue if C-runtime in these 2 dlls are not compiled the same way.
|
||||
|
||||
There are also advanced scenarios that user want to customize memory allocation. Napa provides APIs for customizing memory allocator as well.
|
||||
|
||||
### Recommended way of allocate memory.
|
||||
TBD
|
||||
|
||||
### Customize memory allocation
|
||||
|
||||
TBD
|
||||
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
# namespace `metric`
|
||||
|
||||
## Table of Contents
|
||||
- [Metric basics](#metric-basics)
|
||||
- [C++ API](#c-api)
|
||||
- interface [`Metric`](#interface-metric)
|
||||
- interface [`MetricProvider`](#interface-metric-provider)
|
||||
- function [`MetricProvider& GetMetricProvider()`](#metricprovider-getmetricprovider)
|
||||
- [JavaScript API](#javascript-api)(#javascript-api)
|
||||
- enum [`MetricType`](#metrictype)
|
||||
- class [`Metric`](#class-metric)
|
||||
- [`set(value: number, dimensions?: string[]): void`](#set-value-number-dimensions-string)
|
||||
- [`increment(dimensions?: string[]): void`]();
|
||||
- [`decrement(dimensions?: string[]): void`]();
|
||||
- function [`get(section: string, name: string, type: MetricType, dimensionNames: string[])`]()
|
||||
|
||||
- [Using custom metric providers](#using-custom-metric-providers)
|
||||
- [Developing custom metric providers](#developing-custom-metric-providers)
|
||||
|
||||
## Metric basics
|
||||
Similar as logging, metric a basic requirement for creating monitorable services. `napajs` metric API enables developers to use their own metric system in both JavaScript and C++ (addon) world.
|
||||
|
||||
A metric may contain following information:
|
||||
- (Required) Section: The group or category of the metric.
|
||||
- (Required) Name: Name of the metric. Section/Name combination should be unique in the system.
|
||||
- (Required) Metric type: Type of the metric, which can be
|
||||
- Number: A absolute number, e.g: PrivateBytes.
|
||||
- Rate: A flowing volume in number, e.g: QueryPerSecond.
|
||||
- Percentile: A absolute number that needs to be sampled by percentiles, e.g: SuccessLatency.
|
||||
- (Required) Dimensions: A metric can have multiple dimensions, each dimension can bind with a string value at runtime. e.g: IncomingRequestRate can have 2 dimensions: ['client-id', 'request-type'].
|
||||
|
||||
## C++ API
|
||||
### Interface Metric
|
||||
```cpp
|
||||
/// <summary> Enumeration of metric type. </summary>
|
||||
enum class MetricType {
|
||||
Number = 0,
|
||||
Rate,
|
||||
Percentile,
|
||||
};
|
||||
|
||||
/// <summary> Interface to represents a multi-dimensional metric with a maximum dimensionality of 64. </summary>
|
||||
class Metric {
|
||||
public:
|
||||
|
||||
/// <summary> Sets a metric value with varidic dimension arguments. </summary>
|
||||
/// <param name="value"> Int64 value. </param>
|
||||
/// <param name="numberOfDimensions"> Number of dimensions being set. </param>
|
||||
/// <param name="dimensionValues"> Array of dimension value names. </param>
|
||||
/// <returns> Success/Fail. </returns>
|
||||
/// <remarks>
|
||||
/// The number of dimension values must exactly match the number of dimensions provided when
|
||||
/// creating this metric.
|
||||
/// </remarks>
|
||||
virtual bool Set(int64_t value, size_t numberOfDimensions, const char* dimensionValues[]) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Increments a metric value with variadic dimension arguments.
|
||||
/// Use mainly to simplify rate counters.
|
||||
/// </summary>
|
||||
/// <param name="value"> UInt64 value to increment. </param>
|
||||
/// <param name="numberOfDimensions"> Number of dimensions being set. </param>
|
||||
/// <param name="dimensionValues"> Array of dimension value names. </param>
|
||||
/// <returns> Success/Fail. </returns>
|
||||
/// <remarks>
|
||||
/// The number of dimension values must exactly match the number of dimensions
|
||||
/// provided when creating this metric.
|
||||
/// </remarks>
|
||||
virtual bool Increment(uint64_t value, size_t numberOfDimensions, const char* dimensionValues[]) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Decrements metric value with varidic dimension arguments.
|
||||
/// Use mainly to simplify rate counters.
|
||||
/// </summary>
|
||||
/// <param name="value"> UInt64 value to decrement. </param>
|
||||
/// <param name="numberOfDimensions"> Number of dimensions being set. </param>
|
||||
/// <param name="dimensionValues"> Array of dimension value names. </param>
|
||||
/// <returns> Success/Fail. </returns>
|
||||
/// <remarks>
|
||||
/// The number of dimension values must exactly match the number of dimensions
|
||||
/// provided when creating this metric.
|
||||
/// </remarks>
|
||||
virtual bool Decrement(uint64_t value, size_t numberOfDimensions, const char* dimensionValues[]) = 0;
|
||||
|
||||
/// <summary> Explicitly destroys the Metric. </summary>
|
||||
/// <remarks>
|
||||
/// Consumers are not required to call this.
|
||||
/// The MetricProvider owns this class and will automatically perform cleanup on shutdown.
|
||||
/// </remarks>
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
///<summary> Prevent calling delete on the interface. Must use Destroy! </summary>
|
||||
virtual ~Metric() = default;
|
||||
};
|
||||
```
|
||||
### Interface MetricProvider
|
||||
```cpp
|
||||
|
||||
/// <summary> Interface for a generic metric provider. </summary>
|
||||
/// <remarks>
|
||||
/// Ownership of this metric provider belongs to the shared library which created it. Hence the explicit
|
||||
/// Destroy method in this class. To simplify memory management across multiple shared libraries, this class
|
||||
/// can only be created via a factory method provided by the shared library. When it is no longer needed,
|
||||
/// the caller may call Destroy() which will tell the shared library which created it to dispose of the object.
|
||||
/// </remarks>
|
||||
class MetricProvider {
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets or creates a N-dimensional metric. Metric objects are owned and cached by this class.
|
||||
/// Up to 64 dimensions may be used.</summary>
|
||||
/// <param name="section"> Section of the metric.</param>
|
||||
/// <param name="name"> Name of the metric.</param>
|
||||
/// <param name="type"> Type of the metric.</param>
|
||||
/// <param name="dimensions">
|
||||
/// Number of dimensions requested for this metric.
|
||||
/// Represents the size of the array passed in for p_dimensionNames.
|
||||
/// </param>
|
||||
/// <param name="dimensionNames"> Array of dimension names being requested for this metric.</param>
|
||||
/// <remarks>
|
||||
/// The IMetric class returned is owned and cached by this class.
|
||||
/// Callers are not required to call destroy() on the Metric.
|
||||
/// </remarks>
|
||||
virtual Metric* GetMetric(
|
||||
const char* section,
|
||||
const char* name,
|
||||
MetricType type,
|
||||
size_t dimensions,
|
||||
const char* dimensionNames[]) = 0;
|
||||
|
||||
///<summary> Explicitly destroys the metric provider. </summary>
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
///<summary> Prevent calling delete on the interface. Must use Destroy! </summary>
|
||||
virtual ~MetricProvider() = default;
|
||||
};
|
||||
```
|
||||
### function `MetricProvider& GetMetricProvider()`
|
||||
```cpp
|
||||
/// <summary> Exports a getter function for retrieves the configured metric provider. </summary>
|
||||
NAPA_API MetricProvider& GetMetricProvider();
|
||||
```
|
||||
## JavaScript API
|
||||
```ts
|
||||
export enum MetricType {
|
||||
Number = 0,
|
||||
Rate,
|
||||
Percentile,
|
||||
}
|
||||
|
||||
export interface Metric {
|
||||
section: string;
|
||||
name: string;
|
||||
|
||||
set(value: number, dimensions?: string[]): void;
|
||||
increment(dimensions?: string[]): void;
|
||||
decrement(dimensions?: string[]): void;
|
||||
}
|
||||
|
||||
export function get(
|
||||
section: string,
|
||||
name: string,
|
||||
type: MetricType,
|
||||
dimensions: string[] = []) : Metric;
|
||||
```
|
||||
|
||||
Example:
|
||||
```ts
|
||||
import * as napa from 'napajs';
|
||||
let metric = napa.metric.get('app1', 'counter1', napa.metric.MetricType.Number, []);
|
||||
metric.increment([]);
|
||||
```
|
||||
## Using custom metric providers
|
||||
Developers can hook up custom metric provider by calling the following before creation of any zones:
|
||||
```ts
|
||||
napa.runtime.setPlatformSettings({
|
||||
"metricProvider": "<custom-metric-provider-module-name>"
|
||||
}
|
||||
```
|
||||
## Developing custom metric providers
|
||||
TBD
|
|
@ -1,32 +1,35 @@
|
|||
# namespace `store`
|
||||
|
||||
## Table of Contents
|
||||
- [`create(id: string): Store`](#create)
|
||||
- [`get(id: string): Store`](#get)
|
||||
- [`getOrCreate(id: string): Store`](#getOrCreate)
|
||||
- [`count: number`](#count)
|
||||
- interface [`Store`](#store)
|
||||
- [`store.id: string`](#store-id)
|
||||
- [`store.set(key: string, value: any): void`](#store-set)
|
||||
- [`store.get(key: string): any`](#store-get)
|
||||
- [`store.has(key: string): boolean`](#store-has)
|
||||
- [`store.size: number`](#store-size)
|
||||
- [Introduction to Store](#introduction-to-store)
|
||||
- [API](#api)
|
||||
- [`create(id: string): Store`](#create-id-string-store)
|
||||
- [`get(id: string): Store`](#get-id-string-store)
|
||||
- [`getOrCreate(id: string): Store`](#getOrCreate-id-string-store)
|
||||
- [`count: number`](#count-number)
|
||||
- interface [`Store`](#interface-store)
|
||||
- [`store.id: string`](#store-id-string)
|
||||
- [`store.set(key: string, value: any): void`](#store-set-key-string-value-any)
|
||||
- [`store.get(key: string): any`](#store-get-key-string-any)
|
||||
- [`store.has(key: string): boolean`](#store-has-key-string-boolean)
|
||||
- [`store.size: number`](#store-size-number)
|
||||
|
||||
## APIs
|
||||
Store API is introduced as a necessary complement of sharing [transportable](transport.md#transportable) objects across JavaScript threads, on top of passing objects via arguments. During `store.set`, values marshalled into JSON and stored in process heap, so all threads can access it, and unmarshalled while users retrieve them via `store.get`.
|
||||
## Introduction to Store
|
||||
Store API is introduced as a necessary complement of sharing [transportable](transport.md#transportable-types) objects across JavaScript threads, on top of passing objects via arguments. During `store.set`, values marshalled into JSON and stored in process heap, so all threads can access it, and unmarshalled while users retrieve them via `store.get`.
|
||||
|
||||
Though very convenient, it's not recommended to use store to pass values within a transaction or request, since its overhead is more than passing objects by arguments (there are extra locking, etc.). Besides, developers have the obligation to delete the key after usage, while it's automatically managed by reference counting in passing arguments.
|
||||
|
||||
## API
|
||||
Following APIs are exposed to create, get and operate upon stores.
|
||||
|
||||
### <a name="create"></a>create(id: string): Store
|
||||
### create(id: string): Store
|
||||
It creates a store by a string identifer that can be used to get the store later. When all references to the store from all JavaScript VMs are cleared, the store will be destroyed. Thus always keep a reference at global or module scope is usually a good practice using `Store`. Error will be thrown if the id already exists.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
let store = napa.store.create('store1');
|
||||
```
|
||||
### <a name="get"></a>get(id: string): Store
|
||||
### get(id: string): Store
|
||||
It gets a reference of store by a string identifier. `undefined` will be returned if the id doesn't exist.
|
||||
|
||||
Example:
|
||||
|
@ -34,38 +37,38 @@ Example:
|
|||
let store = napa.store.get('store1');
|
||||
```
|
||||
|
||||
### <a name="getOrCreate"></a>getOrCreate(id: string): Store
|
||||
### getOrCreate(id: string): Store
|
||||
It gets a reference of store by a string identifier, or creates it if the id doesn't exist. This API is handy when you want to create a store in code that is executed by every worker of a zone, since it doesn't break symmetry.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
let store = napa.store.getOrCreate('store1');
|
||||
```
|
||||
### <a name="count"></a>count: number
|
||||
### count: number
|
||||
It returns count of living stores.
|
||||
|
||||
### <a name="store"></a>interface `Store`
|
||||
### Interface `Store`
|
||||
Interface that let user to put and get objects across multiple JavaScript VMs.
|
||||
|
||||
### <a name="store-id"></a>store.id: string
|
||||
### store.id: string
|
||||
It gets the string identifier for the store.
|
||||
|
||||
### <a name="store-set"></a>store.set(key: string, value: any): void
|
||||
It puts a [transportable](transport.md#transportable) value into store with a string key. If key already exists, new value will override existing value.
|
||||
### store.set(key: string, value: any): void
|
||||
It puts a [transportable](transport.md#transportable-types) value into store with a string key. If key already exists, new value will override existing value.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
store.set('status', 1);
|
||||
```
|
||||
### <a name="store-get"></a>store.get(key: string): any
|
||||
It gets a [transportable](transportable.md#transportable) value from the store by a string key. If key doesn't exist, `undefined` will be returned.
|
||||
### store.get(key: string): any
|
||||
It gets a [transportable](transportable.md#transportable-types) value from the store by a string key. If key doesn't exist, `undefined` will be returned.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
let value = store.get('status');
|
||||
assert(value === 1);
|
||||
```
|
||||
### <a name="store-has"></a>store.has(key: string): boolean
|
||||
### store.has(key: string): boolean
|
||||
It tells if a key exists in current store.
|
||||
|
||||
Example:
|
||||
|
@ -73,5 +76,5 @@ Example:
|
|||
assert(store.has('status'))
|
||||
```
|
||||
|
||||
### <a name="store-size"></a>store.size: number
|
||||
### store.size: number
|
||||
It tells how many keys are stored in current store.
|
|
@ -1,21 +1,21 @@
|
|||
# namespace `sync`
|
||||
## Table of Contents
|
||||
- class [`Lock`](#lock)
|
||||
- [`lock.guard(func: () => any): any`](#lock-guard)
|
||||
- class [`ReadWriteLock`](#rwlock)
|
||||
- [`rwlock.guardRead(func: () => any): any`](#rwlock-guardRead)
|
||||
- [`rwlock.guardWrite(func: () => any): any`](#rwlock-guardWrite)
|
||||
- class [`Lock`](#class-lock)
|
||||
- [`lock.guard(func: () => any): any`](#lock-guard-func-any-any)
|
||||
- class [`ReadWriteLock`](#class-readwritelock)
|
||||
- [`rwlock.guardRead(func: () => any): any`](#rwlock-guardread-func-any-any)
|
||||
- [`rwlock.guardWrite(func: () => any): any`](#rwlock-guardwrite-func-any-any)
|
||||
|
||||
## APIs
|
||||
Namespace `sync` deal with synchronization between threads in Napa. `Lock` and `ReadWriteLock` are provided for exclusive and shared mutex scenarios.
|
||||
## <a name="lock"></a> Class `Lock`
|
||||
## Class `Lock`
|
||||
Exclusive Lock, which is [transportable](transport.md#transportable) across JavaScript threads.
|
||||
|
||||
Example: Creating a lock with operator `new`.
|
||||
```ts
|
||||
let lock = new napa.sync.Lock();
|
||||
```
|
||||
### <a name="lock-guard"></a> lock.guard(func: () => any): any
|
||||
### lock.guard(func: () => any): any
|
||||
Run input function synchronously and obtain the lock during its execution, returns what the function returns, or throws error if input function throws. Lock will be released once execution finishes.
|
||||
```ts
|
||||
try {
|
||||
|
@ -29,7 +29,7 @@ catch(error) {
|
|||
console.log(error);
|
||||
}
|
||||
```
|
||||
## <a name="rwlock"></a> Class `ReadWriteLock`
|
||||
## Class `ReadWriteLock`
|
||||
Read-write lock, which is [transportable](transport.md#transportable) across JavaScript threads.
|
||||
|
||||
Example: Creating a read-write lock with operator `new`.
|
||||
|
@ -37,7 +37,7 @@ Example: Creating a read-write lock with operator `new`.
|
|||
let lock = new napa.sync.ReadWriteLock();
|
||||
```
|
||||
|
||||
### <a name="rwlock-guardRead"></a> rwlock.guardRead(func: () => any): any
|
||||
### rwlock.guardRead(func: () => any): any
|
||||
Run input function synchronously and obtain the read (shared) lock during its execution, returns what the function returns, or throws error if input function throws. Read lock will be released once execution finishes. Multiple guardRead across threads can enter simutenously while no pending guardWrite.
|
||||
|
||||
```ts
|
||||
|
@ -53,7 +53,7 @@ catch(error) {
|
|||
}
|
||||
```
|
||||
|
||||
### <a name="rwlock-guardWrite"></a> rwlock.guardWrite(func: () => any): any
|
||||
### rwlock.guardWrite(func: () => any): any
|
||||
|
||||
Run input function synchronously and obtain the write (exclusive) lock during its execution, returns what the function returns, or throws error if input function throws. Write lock will be released once execution finishes. Multiple guardWrite across threads cannot entered simutenously, and will always wait if there is any pending guardRead.
|
||||
|
||||
|
|
|
@ -1,54 +1,58 @@
|
|||
# namespace `transport`
|
||||
|
||||
## Table of Contents
|
||||
- [Transporting JavaScript values](#transport)
|
||||
- [`isTransportable(jsValue: any): boolean`](#isTransportable)
|
||||
- [`register(transportableClass: new(...args: any[]) => any): void`](#register)
|
||||
- [`marshallTransform(jsValue: any, context: TransportContext): any`](#marshallTransform) (unstable)
|
||||
- [`marshall(jsValue: any, context: TransportContext): string`](#marshall)
|
||||
- [`unmarshall(json: string, context: TransportableContext): any`](#unmarshall)
|
||||
- class [`TransportContext`](#transportContext)
|
||||
- [`context.saveShared(object: memory.Shareable): void`]
|
||||
- [`context.loadShared(handle: memory.Handle): memory.Shareable`]
|
||||
- [`context.sharedCount: number`]
|
||||
- interface [`Transportable`](#transportable)
|
||||
- [`transportable.cid: string`](#transportable-cid)
|
||||
- [`transportable.marshall(context: TransportContext): object`](#transportable-marshall)
|
||||
- [`transportable.unmarshall(payload: object, context: TransportContext): void`](#transportable-unmarshall)
|
||||
- abstract class [`TransportableObject`](#transportableObject)
|
||||
- [`transportableObject.cid: string`](#transportableObject-cid)
|
||||
- [`transportableObject.marshall(context: TransportContext): object`](#transportableObject-marshall)
|
||||
- [`transportableObject.unmarshall(payload: object, context: TransportContext): void`](#transportableObject-unmarshall)
|
||||
- abstract [`transportableObject.save(payload: object, context: TransportContext): void`](#transportableObject-save)
|
||||
- abstract [`transportableObject.load(payload: object, context: TransportContext): void`](#transportableObject-load)
|
||||
- class [`AutoTransportable`](#autoTransportable)
|
||||
- decorator [`cid`](#cid-decorator)
|
||||
- [Implementing user transportable classes](#implement)
|
||||
- [Transporting JavaScript values](#transporting-javascript-values)
|
||||
- [Transportable types](#transportable-types)
|
||||
- [Constructor ID](#constructor-id)
|
||||
- [Transport context](#transport-context)
|
||||
- API
|
||||
- [`isTransportable(jsValue: any): boolean`](#istransportable-jsvalue-any)
|
||||
- [`register(transportableClass: new(...args: any[]) => any): void`](#register-transportableclass-new-args-any-any-void)
|
||||
- [`marshallTransform(jsValue: any, context: TransportContext): any`](#marshalltransform-jsvalue-any-context-transportcontext-any) (unstable)
|
||||
- [`marshall(jsValue: any, context: TransportContext): string`](#marshall-jsvalue-any-context-transportcontext-string)
|
||||
- [`unmarshall(json: string, context: TransporteContext): any`](#unmarshall-json-string-context-transportecontext-any)
|
||||
- class [`TransportContext`](#class-transportcontext)
|
||||
- [`context.saveShared(object: memory.Shareable): void`](context-saveshared-object-memory-shareable-void)
|
||||
- [`context.loadShared(handle: memory.Handle): memory.Shareable`](context-loadshared-handle-memory-handle-shareable)
|
||||
- [`context.sharedCount: number`](context-sharedcount-number)
|
||||
- interface [`Transportable`](#interface-transportable)
|
||||
- [`transportable.cid: string`](#transportable-cid-string)
|
||||
- [`transportable.marshall(context: TransportContext): object`](#transportable-marshall-context-transportcontext-object)
|
||||
- [`transportable.unmarshall(payload: object, context: TransportContext): void`](#transportable-unmarshall-payload-object-context-transportcontext-void)
|
||||
- abstract class [`TransportableObject`](#abstract-class-transportableobject)
|
||||
- [`transportableObject.cid: string`](#transportableobject-cid-string)
|
||||
- [`transportableObject.marshall(context: TransportContext): object`](#transportableobject-marshall-context-transportcontext-object)
|
||||
- [`transportableObject.unmarshall(payload: object, context: TransportContext): void`](#transportableobject-unmarshall-payload-object-context-transportcontext-void)
|
||||
- abstract [`transportableObject.save(payload: object, context: TransportContext): void`](#abstract-transportableobject-save-payload-object-context-transportcontext-void)
|
||||
- abstract [`transportableObject.load(payload: object, context: TransportContext): void`](#abstract-transportableobject-load-payload-object-context-transportcontext-void)
|
||||
- class [`AutoTransportable`](#class-autotransportable)
|
||||
- decorator [`cid`](#decorator-cid)
|
||||
- [Implementing user transportable classes](#implementing-user-transportable-classes)
|
||||
|
||||
## <a name="transport"></a>Transporting JavaScript values
|
||||
## Transporting JavaScript values
|
||||
Existing JavaScript engines are not designed for running JavaScript across multiple VMs, which means every VM manages their own heap. Passing values from one VM to another has to be marshalled/unmarshalled. The size of payload and complexity of object will greatly impact communication efficiency. In Napa, we try to work out a design pattern for efficient object sharing, based on the fact that all JavaScript VMs (exposed as workers) reside in the same process, and native objects can be wrapped and exposed as JavaScripts objects.
|
||||
|
||||
Following concepts are introduced to implement this pattern:
|
||||
|
||||
### Transportable types
|
||||
Transportable types are JavaScript types that can be passed or shared transparently across Napa workers. They are used as value types for passing arguments in [`zone.broadcast`](zone.md#broadcast-function) / [`zone.execute`](zone.md#execute-function), and sharing objects in key/value pairs via [`store.set`](store.md#store-set) / [`store.get`](store.md#store-get).
|
||||
Transportable types are JavaScript types that can be passed or shared transparently across Napa workers. They are used as value types for passing arguments in [`zone.broadcast`](zone.md#broadcast-function) / [`zone.execute`](zone.md#execute-function), and sharing objects in key/value pairs via [`store.set`](store.md#store-set-key-string-value-any) / [`store.get`](store.md#store-get-key-string-any).
|
||||
|
||||
Transportable types are:
|
||||
- JavaScript primitive types: undefined, null, boolean, number, string
|
||||
- Object (TypeScript class) that implement [`Transportable`](#transportable) interface
|
||||
- Object (TypeScript class) that implement [`Transportable`](#interface-transportable) interface
|
||||
- Array or plain JavaScript object that is composite pattern of above.
|
||||
|
||||
### <a name="cid"></a>Constructor ID (cid)
|
||||
For user classes that implement [`Transportable`](#transportable) interface, Napa uses Constructor ID (`cid`) to lookup constructors for creating a right object from a string payload. `cid` is marshalled as a part of the payload. During unmarshalling, transport layer will extract the `cid`, create an object instance using the constructor associated with it, and then call unmarshall on the object.
|
||||
### Constructor ID (cid)
|
||||
For user classes that implement [`Transportable`](#interface-transportable) interface, Napa uses Constructor ID (`cid`) to lookup constructors for creating a right object from a string payload. `cid` is marshalled as a part of the payload. During unmarshalling, transport layer will extract the `cid`, create an object instance using the constructor associated with it, and then call unmarshall on the object.
|
||||
|
||||
It's class developer's responsibility to choose the right `cid` for your class. To avoid conflict, we suggest to use the combination of module.id and class name as `cid`. Developer can use class decorator [`cid`](#cid-decorator) to register a user Transportable class automatically, when using TypeScript with decorator feature enabled. Or call [`transport.register`](#register) manually during module initialization.
|
||||
It's class developer's responsibility to choose the right `cid` for your class. To avoid conflict, we suggest to use the combination of module.id and class name as `cid`. Developer can use class decorator [`cid`](#decorator-cid) to register a user Transportable class automatically, when using TypeScript with decorator feature enabled. Or call [`transport.register`](#register-transportableclass-new-args-any-any-void) manually during module initialization.
|
||||
|
||||
### <a name="transportContext"></a>Transport context
|
||||
### Transport context
|
||||
There are states that cannot be saved or loaded in serialized form (like std::shared_ptr), or it's very inefficient to serialize (like JavaScript function). Transport context is introduced to help in these scenarios. TransportContext objects can be passed from one JavaScript VM to another, or stored in native world, so lifecycle of shared native objects extended by using TransportContext. An example of `Transportable` implementation using TransportContext is [`ShareableWrap`](..\..\inc\napa\module\shareable-wrap.h).
|
||||
|
||||
## API
|
||||
|
||||
### <a name="isTransportable"></a>isTransportable(jsValue: any): boolean
|
||||
### isTransportable(jsValue: any): boolean
|
||||
It tells whether a JavaScript value is transportable or not.
|
||||
```ts
|
||||
// JS primitives
|
||||
|
@ -85,7 +89,7 @@ class B {
|
|||
// Not transportable JS class. (not registered with @cid).
|
||||
assert(!transport.isTransportable(new B()));
|
||||
```
|
||||
### <a name="register"></a>register(transportableClass: new(...args: any[]) => any): void
|
||||
### register(transportableClass: new(...args: any[]) => any): void
|
||||
Register a `Transportable` class before transport layer can marshall/unmarshall its instances.
|
||||
User can also use class decorator [`@cid`](#cid-decorator) for class registration.
|
||||
|
||||
|
@ -101,7 +105,7 @@ class A extends transport.AutoTransportable {
|
|||
// Explicitly register class A in transport.
|
||||
transport.register(A);
|
||||
```
|
||||
### <a name="marshallTransform"></a>marshallTransform(jsValue: any, context: TransportContext): any
|
||||
### marshallTransform(jsValue: any, context: TransportContext): any
|
||||
*unstable - may change in future iterations
|
||||
|
||||
Performing marshalling transform on an arbitary JavaScript value, if input is transportable, a plain JavaScript value will be returned. Otherwise an error will be thrown.
|
||||
|
@ -122,8 +126,8 @@ class SomeClass extends transport.TransportableObject {
|
|||
//...
|
||||
}
|
||||
```
|
||||
### <a name="marshall"></a>marshall(jsValue: any, context: TransportContext): string
|
||||
Marshall a [transportable](#transportable) JavaScript value into a JSON payload with a [`TransportContext`](#transportContext). Error will be thrown if the value is not transportable.
|
||||
### marshall(jsValue: any, context: TransportContext): string
|
||||
Marshall a [transportable](#transportable-types) JavaScript value into a JSON payload with a [`TransportContext`](#transport-context). Error will be thrown if the value is not transportable.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
|
@ -131,40 +135,40 @@ let context = transport.createTransportContext();
|
|||
let jsonPayload = transport.marshall([1, 'string', napa.memory.crtAllocator], context);
|
||||
console.log(jsonPayload);
|
||||
```
|
||||
### <a name="unmarshall"></a>unmarshall(json: string, context: TransportableContext): any
|
||||
Unmarshall an [transportable](#transportable) JavaScript value from a JSON payload with a [`TransportContext`](#transportContext). Error will be thrown if `cid` property is found and not registered with transport layer.
|
||||
### unmarshall(json: string, context: TransportContext): any
|
||||
Unmarshall an [transportable](#transportable-types) JavaScript value from a JSON payload with a [`TransportContext`](#transport-context). Error will be thrown if `cid` property is found and not registered with transport layer.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
let value = transport.unmarshall(jsonPayload, context);
|
||||
```
|
||||
|
||||
## <a name="transportContext-class"></a>Class `TransportContext`
|
||||
Class for [Transport Context](#transportContext), that stores shared pointers and functions during marshall/unmarshall.
|
||||
### <a name="context-saveShared"></a> context.saveShared(object: memory.Shareable): void
|
||||
## Class `TransportContext`
|
||||
Class for [Transport Context](#transport-context), that stores shared pointers and functions during marshall/unmarshall.
|
||||
### context.saveShared(object: memory.Shareable): void
|
||||
Save a shareable object in context.
|
||||
|
||||
### <a name="context-loadShared"></a> context.loadShared(handle: memory.Handle): memory.Shareable
|
||||
### context.loadShared(handle: memory.Handle): memory.Shareable
|
||||
Load a shareable object from handle.
|
||||
|
||||
### <a name="context-sharedCount"></a> context.sharedCount: number
|
||||
### context.sharedCount: number
|
||||
Count of shareable objects saved in current context.
|
||||
|
||||
## <a name="transportable"></a>Interface `Transportable`
|
||||
## Interface `Transportable`
|
||||
Interface for Transportable object.
|
||||
### <a name="transportable-cid"></a>transportable.cid: string
|
||||
Get accessor for [Constructor ID](#cid). It is used to lookup constructor for payload of current class.
|
||||
### transportable.cid: string
|
||||
Get accessor for [Constructor ID](#constructor-id). It is used to lookup constructor for payload of current class.
|
||||
|
||||
### <a name="transportable-marshall"></a>transportable.marshall(context: TransportContext): object
|
||||
Marshall transform this object into a plain JavaScript object with the help of [TransportContext](#transportContext).
|
||||
### transportable.marshall(context: TransportContext): object
|
||||
Marshall transform this object into a plain JavaScript object with the help of [TransportContext](#transport-context).
|
||||
|
||||
### <a name="transportable-unmarshall"></a>transportable.unmarshall(payload: object, context: TransportContext): void
|
||||
### transportable.unmarshall(payload: object, context: TransportContext): void
|
||||
Unmarshall transform marshalled payload into current object.
|
||||
|
||||
## <a name="transportableObject"></a>Abstract class `TransportableObject`
|
||||
### <a name="cid-decorator"></a>Decorator `cid`
|
||||
## Abstract class `TransportableObject`
|
||||
### Decorator `cid`
|
||||
|
||||
## <a name="implement"></a>Implementing User Transportable Classes
|
||||
## Implementing User Transportable Classes
|
||||
### JavaScript class
|
||||
#### Extending TransportableObject
|
||||
### Addon class
|
||||
|
|
106
docs/api/zone.md
106
docs/api/zone.md
|
@ -1,33 +1,33 @@
|
|||
# namespace `zone`
|
||||
|
||||
## Table of Contents
|
||||
- [`create(id: string, settings: ZoneSettings = DEFAULT_SETTINGS): Zone`](#create)
|
||||
- [`getOrCreate(id: string, settings: ZoneSettings = DEFAULT_SETTINGS): Zone`](#getOrCreate)
|
||||
- [`get(id: string): Zone`](#get)
|
||||
- [`current: Zone`](#current)
|
||||
- [`node: Zone`](#node)
|
||||
- interface [`ZoneSettings`](#zoneSettings)
|
||||
- [`settings.workers: number`](#settings-workers)
|
||||
- [`DEFAULT_SETTINGS: ZoneSettings`](#defaultSettings)
|
||||
- interface [`Zone`](#zone)
|
||||
- [`zone.id: string`](#zone-id)
|
||||
- [`zone.broadcast(code: string): Promise<void>`](#broadcast-code)
|
||||
- [`zone.broadcast(function: (...args: any[]) => void, args: any[]): Promise<void>`](#broadcast-function)
|
||||
- [`zone.broadcastSync(code: string): void`](#broadcastSync-code)
|
||||
- [`zone.broadcastSync(function: (...args: any[]) => void, args: any[]): void`](#broadcastSnc-function)
|
||||
- [`zone.execute(moduleName: string, functionName: string, args: any[], timeout: number): Promise<any>`](#execute-name)
|
||||
- [`zone.execute(function: (...args[]) => any, args: any[], timeout: number): Promise<any>`](#execute-function)
|
||||
- [`zone.executeSync(moduleName: string, functionName: string, args: any[], timeout: number): any`](#executeSync-name)
|
||||
- [`zone.executeSync(function: (...args: any[]) => any, args: any[], timeout: number): any`](#executeSync-function)
|
||||
- interface [`ExecuteResult`](#executeResult)
|
||||
- [`result.value: any`](#result-value)
|
||||
- [`result.payload: string`](#result-payload)
|
||||
- [`result.transportContext: transport.TransportContext`](#result-transportContext)
|
||||
- [`create(id: string, settings: ZoneSettings = DEFAULT_SETTINGS): Zone`](#create-id-string-settings-zonesettings-default_settings-zone)
|
||||
- [`getOrCreate(id: string, settings: ZoneSettings = DEFAULT_SETTINGS): Zone`](#getOrCreate-id-string-settings-zonesettings-default_settings-zone)
|
||||
- [`get(id: string): Zone`](#get-id-string-zone)
|
||||
- [`current: Zone`](#current-zone)
|
||||
- [`node: Zone`](#node-zone)
|
||||
- interface [`ZoneSettings`](#interface-zonesettings)
|
||||
- [`settings.workers: number`](#settings-workers-number)
|
||||
- object [`DEFAULT_SETTINGS: ZoneSettings`](#object-default_settings-zonesettings)
|
||||
- interface [`Zone`](#interface-zone)
|
||||
- [`zone.id: string`](#zone-id-string)
|
||||
- [`zone.broadcast(code: string): Promise<void>`](#zone-broadcast-code-string-promise-void)
|
||||
- [`zone.broadcast(function: (...args: any[]) => void, args: any[]): Promise<void>`](#zone-broadcast-function-args-any-void-args-any-promise-void)
|
||||
- [`zone.broadcastSync(code: string): void`](#zone-broadcastsync-code-string-void)
|
||||
- [`zone.broadcastSync(function: (...args: any[]) => void, args: any[]): void`](#zone-broadcastsync-function-args-any-void-args-any-void)
|
||||
- [`zone.execute(moduleName: string, functionName: string, args: any[], timeout: number): Promise<ExecuteResult>`](#zone-execute-modulename-string-functionname-string-args-any-timeout-number-promise-executeresult)
|
||||
- [`zone.execute(function: (...args[]) => any, args: any[], timeout: number): Promise<ExecuteResult>`](#zone-execute-function-args-any-args-any-timeout-number-promise-executeresult)
|
||||
- [`zone.executeSync(moduleName: string, functionName: string, args: any[], timeout: number): ExecuteResult`](#zone-executesync-modulename-string-functionname-string-args-any-timeout-number-executeresult)
|
||||
- [`zone.executeSync(function: (...args: any[]) => any, args: any[], timeout: number): ExecuteResult`](#zone-executesync-function-args-any-any-args-any-timeout-number-executeresult)
|
||||
- interface [`ExecuteResult`](#interface-executeresult)
|
||||
- [`result.value: any`](#result-value-any)
|
||||
- [`result.payload: string`](#result-payload-string)
|
||||
- [`result.transportContext: transport.TransportContext`](#result-transportcontext-transport-transportcontext)
|
||||
|
||||
## API
|
||||
### <a name="create"></a>create(id: string, settings: ZoneSettings): Zone
|
||||
### create(id: string, settings: ZoneSettings): Zone
|
||||
|
||||
It creates a Napa zone with a string id. If zone with the id is already created, error will be thrown. [`ZoneSettings`](#zoneSettings) can be specified for creating zones.
|
||||
It creates a Napa zone with a string id. If zone with the id is already created, error will be thrown. [`ZoneSettings`](#interface-zonesettings) can be specified for creating zones.
|
||||
|
||||
Example 1: Create a zone with id 'zone1', using default ZoneSettings.
|
||||
```ts
|
||||
|
@ -40,7 +40,7 @@ let zone = napa.zone.create('zone1', {
|
|||
workers: 1
|
||||
});
|
||||
```
|
||||
### <a name="getOrCreate"></a>getOrCreate(id: string, settings: ZoneSettings): Zone
|
||||
### getOrCreate(id: string, settings: ZoneSettings): Zone
|
||||
It gets a reference of zone by an id if a zone with the id already exists, otherwise create a new one and return its reference.
|
||||
|
||||
Example:
|
||||
|
@ -49,48 +49,48 @@ let zone = napa.zone.getOrCreate('zone1', {
|
|||
workers: 4
|
||||
});
|
||||
```
|
||||
### <a name="get"></a>get(id: string): Zone
|
||||
### get(id: string): Zone
|
||||
It gets a reference of zone by an id. Error will be thrown if the zone doesn't exist.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
let zone = napa.zone.get('zone1');
|
||||
```
|
||||
### <a name="current"></a>current: Zone
|
||||
### current: Zone
|
||||
It returns a reference of the zone of current running isolate. If it's under node, it returns the [node zone](#node).
|
||||
|
||||
Example: Get current zone.
|
||||
```ts
|
||||
let zone = napa.zone.current;
|
||||
```
|
||||
### <a name="node"></a>node: Zone
|
||||
### node: Zone
|
||||
It returns a reference to the node zone. It is equivalent to `napa.zone.get('node')`;
|
||||
|
||||
Example:
|
||||
```ts
|
||||
let zone = napa.zone.node;
|
||||
```
|
||||
## <a name="zoneSettings"></a>Interface `ZoneSettings`
|
||||
Settings for zones, which will be specified during creation of zones. If not specified, [DEFAULT_SETTINGS](#defaultSettings) will be used.
|
||||
## Interface `ZoneSettings`
|
||||
Settings for zones, which will be specified during creation of zones. If not specified, [DEFAULT_SETTINGS](#object-defaultSettings) will be used.
|
||||
|
||||
### <a name="settings-workers"></a>settings.workers: number
|
||||
### settings.workers: number
|
||||
Number of workers in the zone.
|
||||
|
||||
## <a name="defaultSettings"></a>DEFAULT_SETTINGS
|
||||
## Object `DEFAULT_SETTINGS`
|
||||
Default settings for creating zones.
|
||||
```ts
|
||||
{
|
||||
workers: 2
|
||||
}
|
||||
```
|
||||
## <a name="zone"></a>Interface `Zone`
|
||||
Zone is the basic concept to execute JavaScript and apply policies in Napa. You can find its definition in [Architecture](../../README.md#Architecture). Through Zone API, developers can broadcast JavaScript code on all workers, or execute a function on one of them. When you program against a zone, it is the best practice to ensure all workers within a zone are symmetrical to each other, that you should not assume a worker may maintain its own states.
|
||||
## Interface `Zone`
|
||||
Zone is the basic concept to execute JavaScript and apply policies in Napa. You can find its definition in [Architecture](../../README.md#architecture). Through Zone API, developers can broadcast JavaScript code on all workers, or execute a function on one of them. When you program against a zone, it is the best practice to ensure all workers within a zone are symmetrical to each other, that you should not assume a worker may maintain its own states.
|
||||
|
||||
The two major set of APIs are `broadcast` and `execute`, with both synchronous and asynchronous version plus a few variations on their inputs.
|
||||
### <a name="zone-id"></a>zone.id: string
|
||||
### zone.id: string
|
||||
It gets the id of the zone.
|
||||
|
||||
### <a name="broadcast-code"></a>zone.broadcast(code: string): Promise\<void\>
|
||||
### zone.broadcast(code: string): Promise\<void\>
|
||||
It asynchronously broadcasts a snippet of JavaScript code in a string to all workers, which returns a Promise of void. If any of the workers failed to execute the code, promise will be rejected with an error message.
|
||||
|
||||
Example:
|
||||
|
@ -105,7 +105,7 @@ zone.broadcast('var state = 0;')
|
|||
console.log('broadcast failed.')
|
||||
});
|
||||
```
|
||||
### <a name="broadcast-function"></a>zone.broadcast(function: (...args: any[]) => void, args: any[]): Promise\<void\>
|
||||
### zone.broadcast(function: (...args: any[]) => void, args: any[]): Promise\<void\>
|
||||
It asynchronously broadcasts an annoymous function with its arguments to all workers, which returns a Promise of void. If any of the workers failed to execute the code, promise will be rejected with an error message.
|
||||
|
||||
*Please note that Napa doesn't support closure in 'function' during broadcast.
|
||||
|
@ -123,7 +123,7 @@ zone.broadcast((state) => {
|
|||
console.log('broadcast failed:', error)
|
||||
});
|
||||
```
|
||||
### <a name="broadcastSync-code"></a>zone.broadcastSync(code: string): void
|
||||
### zone.broadcastSync(code: string): void
|
||||
It synchronously broadcasts a snippet of JavaScript code in a string to all workers. If any of the workers failed to execute the code, an error will be thrown with message.
|
||||
|
||||
Example:
|
||||
|
@ -136,7 +136,7 @@ catch (error) {
|
|||
console.log('broadcast failed:', error);
|
||||
}
|
||||
```
|
||||
### <a name="broadcastSync-function"></a>zone.broadcastSync(function: (...args: any[]) => void, args: any[]): void
|
||||
### zone.broadcastSync(function: (...args: any[]) => void, args: any[]): void
|
||||
|
||||
It synchronously broadcasts an annoymous function with its arguments to all workers. If any of the workers failed to execute the code, an error will be thrown with message.
|
||||
|
||||
|
@ -153,8 +153,8 @@ catch (error) {
|
|||
console.log('broadcast failed:', error);
|
||||
}
|
||||
```
|
||||
### <a name="execute-name"></a>zone.execute(moduleName: string, functionName: string, args: any[], timeout: number = 0): Promise\<any\>
|
||||
Execute a function asynchronously on arbitrary worker via module name and function name. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable). It returns a Promise of [`ExecuteResult`](#executeResult). If error happens, either bad code, user exception, or timeout is reached, promise will be rejected.
|
||||
### zone.execute(moduleName: string, functionName: string, args: any[], timeout: number = 0): Promise\<any\>
|
||||
Execute a function asynchronously on arbitrary worker via module name and function name. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable-types). It returns a Promise of [`ExecuteResult`](#interface-executeresult). If error happens, either bad code, user exception, or timeout is reached, promise will be rejected.
|
||||
|
||||
Example: Execute function 'bar' in module 'foo', with arguments [1, 'hello', { field1: 1 }]. 300ms timeout is applied.
|
||||
```ts
|
||||
|
@ -168,9 +168,9 @@ zone.execute('foo', 'bar', [1, "hello", {field1: 1}], 300)
|
|||
|
||||
```
|
||||
|
||||
### <a name="execute-function"></a>zone.execute(function: (...args: any[]) => any, args: any[], timeout: number = 0): Promise\<any\>
|
||||
### zone.execute(function: (...args: any[]) => any, args: any[], timeout: number = 0): Promise\<any\>
|
||||
|
||||
Execute an anonymous function asynchronously on arbitrary worker. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable). It returns a Promise of [`ExecuteResult`](#executeResult). If error happens, either bad code, user exception, or timeout is reached, promise will be rejected.
|
||||
Execute an anonymous function asynchronously on arbitrary worker. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable-types). It returns a Promise of [`ExecuteResult`](#interface-executeresult). If error happens, either bad code, user exception, or timeout is reached, promise will be rejected.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
|
@ -186,9 +186,9 @@ zone.execute((a: number, b: string, c: object) => {
|
|||
|
||||
```
|
||||
|
||||
### <a name="executeSync-name"></a>zone.executeSync(moduleName: string, functionName: string, args: any[], timeout: number = 0): any
|
||||
### zone.executeSync(moduleName: string, functionName: string, args: any[], timeout: number = 0): any
|
||||
|
||||
Execute a function synchronously on arbitrary worker via module name and function name. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable). It returns an [`ExecuteResult`](#executeResult). If error happens, either bad code, user exception, or timeout is reached, error will be thrown.
|
||||
Execute a function synchronously on arbitrary worker via module name and function name. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable-types). It returns an [`ExecuteResult`](#interface-executeresult). If error happens, either bad code, user exception, or timeout is reached, error will be thrown.
|
||||
|
||||
Example: Execute function 'bar' in module 'foo', with arguments [1, 'hello', { field1: 1 }]. 300ms timeout is applied.
|
||||
```ts
|
||||
|
@ -202,8 +202,8 @@ catch (error) {
|
|||
|
||||
```
|
||||
|
||||
### <a name="executeSync-function"></a>zone.executeSync(function: (...args: any[]) => any, args: any[], timeout: number = 0): any
|
||||
Execute an annoymouse function synchronously on arbitrary worker. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable). It returns an [`ExecuteResult`](#executeResult). If error happens, either bad code, user exception, or timeout is reached, error will be thrown.
|
||||
### zone.executeSync(function: (...args: any[]) => any, args: any[], timeout: number = 0): any
|
||||
Execute an annoymouse function synchronously on arbitrary worker. Arguments can be of any JavaScript type that is [transportable](transport.md#transportable-types). It returns an [`ExecuteResult`](#interface-executeresult). If error happens, either bad code, user exception, or timeout is reached, error will be thrown.
|
||||
|
||||
Example: Execute annoymouse function sychronously, with arguments [1, 'hello', { field1: 1 }]. No timeout is applied.
|
||||
```ts
|
||||
|
@ -219,18 +219,18 @@ catch (error) {
|
|||
|
||||
```
|
||||
|
||||
## <a name="executeResult"></a>Interface `ExecuteResult`
|
||||
## Interface `ExecuteResult`
|
||||
Interface to access return value of `zone.execute` or `zone.executeSync`.
|
||||
|
||||
### <a name="result-value"></a>result.value: any
|
||||
JavaScript value returned from function which is invoked from zone.execute/executeSync. Napa marshall/unmarshall [transportable values](transport.md#transportable) between different workers (V8 isolates). Unmarshalling will happen when the first `result.value` is queried.
|
||||
### result.value: any
|
||||
JavaScript value returned from function which is invoked from zone.execute/executeSync. Napa marshall/unmarshall [transportable values](transport.md#transportable-types) between different workers (V8 isolates). Unmarshalling will happen when the first `result.value` is queried.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
let value = result.value;
|
||||
```
|
||||
|
||||
### <a name="result-payload"></a>result.payload: string
|
||||
### result.payload: string
|
||||
Marshalled payload (in JSON) from returned value. This field is for users that want to pass result through to its caller, where unmarshalled value is not required.
|
||||
|
||||
Example:
|
||||
|
@ -238,8 +238,8 @@ Example:
|
|||
let payload = result.payload;
|
||||
```
|
||||
|
||||
### <a name="result-transportContext"></a>result.transportContext: transport.TransportContext
|
||||
[TransportContext](transport.md#transportContext) that is required to unmarshall [`result.payload`](#result-payload) into [`result.value`](#result-value).
|
||||
### result.transportContext: transport.TransportContext
|
||||
[TransportContext](transport.md#transport-context) that is required to unmarshall [`result.payload`](#result-payload-string) into [`result.value`](#result-value-any).
|
||||
|
||||
Example:
|
||||
```ts
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
# Napa.JS Built-ins and Core Modules
|
||||
|
||||
## Node.JS compatible APIs
|
||||
- fs
|
||||
- fs.readFileSync (SUPPORTED)
|
||||
- fs.writeFileSync (SUPPORTED)
|
||||
- others (TBD)
|
||||
- path (consider use Node.JS' implementation)
|
||||
- events
|
||||
- Class: EventEmitter
|
||||
- stream (TBD)
|
||||
- assert (TBD)
|
||||
- assert(value[, message])
|
||||
- assert.deepEqual
|
||||
- assert.deepStrictEqual
|
||||
- assert.doesNotThrow
|
||||
- assert.equal
|
||||
- assert.fail
|
||||
- assert.ifError
|
||||
- assert.notDeepEqual
|
||||
- assert.notDeepStrictEqual
|
||||
- assert.notEqual
|
||||
- assert.notStrictEqual
|
||||
- assert.ok
|
||||
- assert.strictEqual
|
||||
- assert.throws
|
||||
- Global Objects
|
||||
- Class: Buffer (TBD)
|
||||
- __dirname (SUPPORTED)
|
||||
- __pathname (SUPPORTED)
|
||||
- console
|
||||
- console.assert
|
||||
- console.dir
|
||||
- console.error
|
||||
- console.info
|
||||
- console.log (SUPPORTED)
|
||||
- console.time
|
||||
- console.timeEnd
|
||||
- console.trace
|
||||
- console.warn
|
||||
- exports
|
||||
- global (TBD)
|
||||
- module
|
||||
- process (TBD)
|
||||
- require
|
||||
- setImmediate (TBD)
|
||||
- setInterval (TBD)
|
||||
- setTimeout (TBD)
|
||||
|
||||
|
||||
## Napa specific APIs
|
||||
|
||||
- global readonly variable '*__in_napa_container*': Tell if current code is running under a Napa.JS container.
|
|
@ -1,3 +0,0 @@
|
|||
# Napa.JS Container
|
||||
|
||||
TBD
|
|
@ -1,3 +0,0 @@
|
|||
# Napa.JS Module System
|
||||
|
||||
TODO:
|
|
@ -1,3 +0,0 @@
|
|||
# Building C++ Add-ons for Napa.JS
|
||||
|
||||
TODO:
|
|
@ -1,3 +0,0 @@
|
|||
# Coding under Visual Studio Code
|
||||
|
||||
TODO:
|
|
@ -1,3 +0,0 @@
|
|||
# Debugging Napa.JS modules
|
||||
|
||||
TODO:
|
|
@ -1,7 +0,0 @@
|
|||
# Napa.JS Embedders' Guide
|
||||
|
||||
## Embedding Napa.JS to a C++ process
|
||||
TODO:
|
||||
|
||||
## Embedding Napa.JS to a C# process
|
||||
TODO:
|
|
@ -1,7 +1,7 @@
|
|||
# Best practices writing dual-interface modules.
|
||||
|
||||
Dual-interface modules are Napa modules that expose both JavaScript and C++ interfaces. The major purpose of introducing a dual-interface module can be one of the following, or both:
|
||||
1) Sharing C++ objects between host process and Napa add-ons without marshalling/unmarshalling.
|
||||
1) Sharing C++ objects between host process and Napa add-ons without extensive marshalling/unmarshalling.
|
||||
2) Provide 2 implementations - Javascript for agility, and C++ for performance. Developers can quickly iterate ideas in JavaScript, once logic is finalized, we can use C++ interfaces to hook up pretty easily.
|
||||
|
||||
## Pitfalls in dual-interface modules.
|
||||
|
|
|
@ -7,28 +7,28 @@ export enum MetricType {
|
|||
}
|
||||
|
||||
export interface Metric {
|
||||
section: string;
|
||||
name: string;
|
||||
readonly section: string;
|
||||
readonly name: string;
|
||||
|
||||
set(value: number, dimensions?: string[]): void;
|
||||
increment(value: number, dimensions?: string[]): void;
|
||||
decrement(value: number, dimensions?: string[]): void;
|
||||
increment(dimensions?: string[]): void;
|
||||
decrement(dimensions?: string[]): void;
|
||||
}
|
||||
|
||||
/// <summary> A cache for metric wraps. </summary>
|
||||
var _metricsCache: { [key: string]: Metric } = {};
|
||||
|
||||
export function get(section: string, name: string, type: MetricType, dimensions: string[] = []) : Metric {
|
||||
let key: string = (section ? section : "") + "_" + (name ? name : "");
|
||||
let key: string = (section ? section : "") + "\\" + (name ? name : "");
|
||||
|
||||
// Check cache first
|
||||
let metricWrap: Metric = _metricsCache[key];
|
||||
if (metricWrap) {
|
||||
return metricWrap;
|
||||
let metric: Metric = _metricsCache[key];
|
||||
if (metric) {
|
||||
return metric;
|
||||
}
|
||||
|
||||
// Add to cache
|
||||
metricWrap = new binding.MetricWrap(section, name, type, dimensions);
|
||||
let metricWrap: any = new binding.MetricWrap(section, name, type, dimensions);
|
||||
metricWrap.section = section;
|
||||
metricWrap.name = name;
|
||||
_metricsCache[key] = metricWrap;
|
||||
|
|
Загрузка…
Ссылка в новой задаче