Skip to content

Commit

Permalink
Exact interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
samchon committed Jun 25, 2024
1 parent 76cd5be commit d027b4a
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 120 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mutex-server",
"version": "0.6.0",
"version": "0.6.1",
"description": "Mutex Server using WebSocket",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
47 changes: 5 additions & 42 deletions src/MutexAcceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,20 @@ import { ProviderGroup } from "./server/ProviderGroup";
* - available only in NodeJS.
*
* The {@link MutexAcceptor} is a communicator class interacting with the remote client, through
* websocket and [RFC](https://github.com/samchon/tgrid#13-remote-function-call) protocol, in the
* websocket and [RPC](https://tgrid.com/docs/remote-procedure-call/) protocol, in the
* `mutex-server`. The {@link MutexAcceptor} objects are always created by the {@link MutexServer}
* class, whenever a remote client connects to the `mutex-server`.
*
* You can accept or reject the client's connection by calling {@link accept} or {@link reject}
* method. If you {@link accept} the connection, the interaction would be started and the client
* can access to critical component sections of this `mutex-server`.
*
* Also, when declaring this {@link MutexAcceptor} type, you've to define two template arguments,
* *Header* and *Provider*. The *Header* type repersents an initial data gotten from the remote
* client after the connection. I hope you and client not to omit it and utilize it as an
* activation tool to enhance security.
*
* The second template argument *Provider* represents the additional features provided for the
* remote client. If you don't have any plan to provide additional feature to the remote client,
* just declare it as `null`
* Also, when declaring this {@link MutexAcceptor} type, you've to define one template argument,
* *Header*. The *Header* type repersents an initial data gotten from the remote client after
* the connection. I hope you and client not to omit it and utilize it as an activation tool
* to enhance security.
*
* @template Header Type of the header containing initial data.
* @template Provider Type of additional features provided for the remote client.
* @author Jeongho Nam - https://github.com/samchon
*/
export class MutexAcceptor<Header> {
Expand Down Expand Up @@ -73,11 +68,6 @@ export class MutexAcceptor<Header> {
* acquired and tried would be automatically unlocked and cancelled by this `mutex-server`.
* Also, remote critical section components had assigned to the client would be returned, too.
*
* In addition, the disconnection destories all [RFC](https://github.com/samchon/tgrid#13-remote-function-call)s
* between the remote client. Therefore, if the remote client is providing custom features to
* your `mutex-server` and there're uncompleted method calls to the `Provider` through
* `Driver<Controller>`, {@link RuntimeError} exceptions would be thrown.
*
* @param code Closing code.
* @param reason Reason why.
* @throw DomainError when the connection is not online.
Expand Down Expand Up @@ -158,33 +148,6 @@ export class MutexAcceptor<Header> {
return this.base_.state;
}

// /**
// * Get Driver for [RFC](https://github.com/samchon/tgrid#13-remote-function-call).
// *
// * If remote client provides custom features for this `mutex-server`, you can utilize
// * those features thorugh returned `Driver` object by this method. To use this method, you
// * should define the `Controller` template argument, a type of interface who is defining
// * additionla features provided from the remote client.
// *
// * The returned object `Driver` makes to call remote functions, defined in the `Controller`
// * and provided by `Provider` in the remote client, possible. In other words, callling a
// * function in the `Driver<Controller>`, it means to call a matched function in the remote
// * client's `Provider` object.
// *
// * - `Controller`: Definition only
// * - `Driver`: [Remote Function Call](https://github.com/samchon/tgrid#13-remote-function-call)
// *
// * @template Controller An interface for provided features (functions & objects) from the remote client (`Provider`).
// * @template UseParametric Whether to convert type of function parameters to be compatible with their pritimive.
// * @return A `Driver` for the [RFC](https://github.com/samchon/tgrid#13-remote-function-call).
// */
// public getDriver<
// Controller extends object,
// UseParametric extends boolean = false,
// >(): Driver<Controller, UseParametric> {
// return this.base_.getDriver();
// }

/* ----------------------------------------------------------------
HANDSHAKES
---------------------------------------------------------------- */
Expand Down
79 changes: 25 additions & 54 deletions src/MutexConnector.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Driver, WebSocketConnector } from "tgrid";
import { WebSocketConnector } from "tgrid";

import { RemoteBarrier } from "./client/RemoteBarrier";
import { RemoteConditionVariable } from "./client/RemoteConditionVariable";
Expand All @@ -11,7 +11,7 @@ import { ProviderGroup } from "./server/ProviderGroup";
* Mutex server connector for client.
*
* The {@link MutexConnector} is a communicator class who can connect to a remote `mutex-server`
* and interact with it through websocket and [RFC](https://github.com/samchon/tgrid#13-remote-function-call)
* and interact with it through websocket and [RPC](https://tgrid.com/docs/remote-procedure-call/)
* protocol.
*
* You can connect to the websocket `mutex-server` using {@link connect} method. After the
Expand All @@ -28,17 +28,12 @@ import { ProviderGroup } from "./server/ProviderGroup";
* - {@link getBarrier}
* - {@link getLatch}
*
* Also, when declaring this {@link MutexConnector} type, you've to define two template arguments,
* *Header* and *Provider*. The *Header* type repersents an initial data sending to the remote
* `mutex-server` after connection. I hope you not to omit it and utilize it as an activation tool
* to enhance security.
*
* The second template argument *Provider* represents the custom features provided for the remote
* `mutex-server`. If you don't have any plan to provide any feature to the `mutex-server`, just
* declare it as `null`.
* Also, when declaring this {@link MutexConnector} type, you've to define one template argument,
* *Header*. The *Header* type repersents an initial data sending to the remote `mutex-server`
* after connection. I hope you not to omit it and utilize it as an activation tool to
* enhance security.
*
* @template Header Type of the *header* containing initial data.
* @template Provider Type of additional features provided for the remote server. If no plan to provide anything, declare `null`.
* @author Jeongho Nam - https://github.com/samchon
*/
export class MutexConnector<Header> {
Expand All @@ -47,23 +42,16 @@ export class MutexConnector<Header> {
*/
private connector_: WebSocketConnector<Header, null, ProviderGroup>;

/**
* @hidden
*/
private driver_: Driver<ProviderGroup>;

/* -----------------------------------------------------------
CONSTRUCTORS
----------------------------------------------------------- */
/**
* Initializer Constructor.
*
* @param header Initial data sending to the remote server after connection. Hope to use it as an activation tool.
* @param provider Additional feature provided for the remote server. If don't plan to provide anything to the remote server, assign `null`.
*/
public constructor(header: Header) {
this.connector_ = new WebSocketConnector(header, null);
this.driver_ = this.connector_.getDriver();
}

/**
Expand Down Expand Up @@ -97,11 +85,6 @@ export class MutexConnector<Header> {
* tried to get locks through the remote critical section components by calling their methods,
* those methods would throw {@link RuntimeError} exceptions.
*
* Also, the disconnection destories all [RFC](https://github.com/samchon/tgrid#13-remote-function-call)s
* between the remote server. Therefore, if you or server has an additional `Provider` and
* there're uncompleted method calls to the `Provideer` through the `Driver<Controller>`,
* {@link RuntimeError} exceptions would be thrown.
*
* @throw DomainError when the connection is not online.
*/
public async close(): Promise<void> {
Expand Down Expand Up @@ -172,33 +155,9 @@ export class MutexConnector<Header> {
return this.connector_.header;
}

/**
* Get Driver for [RFC](https://github.com/samchon/tgrid#13-remote-function-call).
*
* If your target {@link MutexServer} provides additional features, you can utilize those
* features through returned `Driver` object by this method. To use this method, you should
* define the `Controller` template argument, a type of interface who is defining additional
* features provided from the remote server.
*
* The returned object `Driver` makes to call remote functions, defined in the `Controller`
* and provided by `Provider` in the remote server, possible. In other words, callling a
* function in the `Driver<Controller>`, it means to call a matched function in the remote
* server's `Provider` object.
*
* - `Controller`: Definition only
* - `Driver`: [Remote Function Call](https://github.com/samchon/tgrid#13-remote-function-call)
*
* @template Controller An interface for provided features (functions & objects) from the remote system (`Provider`).
* @template UseParametric Whether to convert type of function parameters to be compatible with their pritimive.
* @return A `Driver` for the [RFC](https://github.com/samchon/tgrid#13-remote-function-call).
*/
public getDriver(): Driver<ProviderGroup> {
return this.driver_;
}

/* -----------------------------------------------------------
THREAD COMPONENTS
----------------------------------------------------------- */
THREAD COMPONENTS
----------------------------------------------------------- */
/**
* Get remote condition variable.
*
Expand All @@ -213,7 +172,7 @@ export class MutexConnector<Header> {
*/
public getConditionVariable(key: string): Promise<RemoteConditionVariable> {
return RemoteConditionVariable.create(
this.driver_.condition_variables,
this.connector_.getDriver().condition_variables,
key,
);
}
Expand All @@ -231,7 +190,7 @@ export class MutexConnector<Header> {
* @return A {@link RemoteMutex} object.
*/
public getMutex(key: string): Promise<RemoteMutex> {
return RemoteMutex.create(this.driver_.mutexes, key);
return RemoteMutex.create(this.connector_.getDriver().mutexes, key);
}

/**
Expand All @@ -251,7 +210,11 @@ export class MutexConnector<Header> {
* @return A {@link RemoteSemaphore} object.
*/
public getSemaphore(key: string, count: number): Promise<RemoteSemaphore> {
return RemoteSemaphore.create(this.driver_.semaphores, key, count);
return RemoteSemaphore.create(
this.connector_.getDriver().semaphores,
key,
count,
);
}

/**
Expand All @@ -271,7 +234,11 @@ export class MutexConnector<Header> {
* @return A {@link RemoteBarrier} object.
*/
public getBarrier(key: string, count: number): Promise<RemoteBarrier> {
return RemoteBarrier.create(this.driver_.barriers, key, count);
return RemoteBarrier.create(
this.connector_.getDriver().barriers,
key,
count,
);
}

/**
Expand All @@ -291,7 +258,11 @@ export class MutexConnector<Header> {
* @return A {@link RemoteLatch} object.
*/
public getLatch(identifier: string, count: number): Promise<RemoteLatch> {
return RemoteLatch.create(this.driver_.latches, identifier, count);
return RemoteLatch.create(
this.connector_.getDriver().latches,
identifier,
count,
);
}
}

Expand Down
21 changes: 8 additions & 13 deletions src/MutexServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,21 @@ import { GlobalGroup } from "./server/GlobalGroup";
*
* The {@link MutexServer} is a class who can open an `mutex-server`. Clients connecting to the
* `mutex-server` would communicate with this server through {@link MutexAcceptor} objects using
* websocket and [RFC](https://github.com/samchon/tgrid#13-remote-function-call) protocol.
* websocket and [RPC](https://tgrid.com/docs/remote-procedure-call/) protocol.
*
* To open the `mutex-server`, call the {@link open} method with your custom callback function
* which would be called whenever a {@link MutexAcceptor} has been newly created by a client's
* connection.
*
* Also, when declaring this {@link MutexServer} type, you've to define two template arguments,
* *Header* and *Provider*. The *Header* type repersents an initial data gotten from the remote
* client after the connection. I hope you and client not to omit it and utilize it as an
* activation tool to enhance security.
*
* The second template argument *Provider* represents the additional features provided for the
* remote client. If you don't have any plan to provide additional feature to the remote client,
* just declare it as `null`.
* Also, when declaring this {@link MutexServer} type, you've to define one template argument,
* *Header*. The *Header* type repersents an initial data gotten from the remote client after
* the connection. I hope you and client not to omit it and utilize it as an activation tool
* to enhance security.
*
* @template Header Type of the *header* containing initial data.
* @template Provider Type of additional features provided for the remote client.
* @author Jeongho Nam - https://github.com/samchon
*/
export class MutexServer<Header, Provider extends object | null> {
export class MutexServer<Header> {
/**
* @hidden
*/
Expand Down Expand Up @@ -112,8 +107,8 @@ export class MutexServer<Header, Provider extends object | null> {
* Therefore, clients who are using the {@link MutexConnector} class, they can't use the
* remote critical section components more.
*
* Also, closing the server means that all of the [RFC](https://github.com/samchon/tgrid#13-remote-function-call)s
* between the server and had connected clients would be destroied. Therefore, all of the [RFC](https://github.com/samchon/tgrid#13-remote-function-call)s
* Also, closing the server means that all of the [RPC](https://tgrid.com/docs/remote-procedure-call/)s
* between the server and had connected clients would be destroied. Therefore, all of the [RPC](https://tgrid.com/docs/remote-procedure-call/)s
* that are not returned (completed) yet would ge {@link RuntimeError} exception.
*/
public close(): Promise<void> {
Expand Down
15 changes: 8 additions & 7 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const HEADER = { password: "some_password" };
interface IModule {
[key: string]: (
factory: ConnectionFactory,
server: MutexServer<IActivation, null>,
server: MutexServer<IActivation>,
) => Promise<void>;
}

Expand All @@ -26,7 +26,7 @@ async function measure(job: () => Promise<void>): Promise<number> {

async function iterate(
factory: ConnectionFactory,
server: MutexServer<IActivation, null>,
server: MutexServer<IActivation>,
path: string,
): Promise<void> {
const fileList: string[] = await fs.promises.readdir(path);
Expand Down Expand Up @@ -71,7 +71,7 @@ async function main(): Promise<void> {
console.log("==========================================================");

// OPEN SERVER
let server: MutexServer<IActivation, null> = new MutexServer();
const server: MutexServer<IActivation> = new MutexServer();
await server.open(PORT, async (acceptor) => {
if (acceptor.header.password === HEADER.password) await acceptor.accept();
else await acceptor.reject();
Expand Down Expand Up @@ -104,17 +104,18 @@ async function main(): Promise<void> {
console.log(` - elapsed time: ${time} ms`);

// MEMORY USAGE
let memory: NodeJS.MemoryUsage = process.memoryUsage();
for (let property in memory) {
let amount: number = memory[property as keyof NodeJS.MemoryUsage] / 10 ** 6;
const memory: NodeJS.MemoryUsage = process.memoryUsage();
for (const property in memory) {
const amount: number =
memory[property as keyof NodeJS.MemoryUsage] / 10 ** 6;
console.log(` - ${property}: ${amount} MB`);
}
console.log("----------------------------------------------------------\n");

//----
// TERMINATE
//----
for (let connector of connectorList)
for (const connector of connectorList)
if (connector.state === MutexConnector.State.OPEN) await connector.close();

await server.close();
Expand Down
2 changes: 1 addition & 1 deletion test/manual/remote-mutex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async function client(index: number, character: string): Promise<void> {

async function main(): Promise<void> {
// OPEN SERVER
const server: MutexServer<string, null> = new MutexServer();
const server: MutexServer<string> = new MutexServer();
await server.open(PORT, async (acceptor) => {
if (acceptor.header === PASSWORD) await acceptor.accept();
else await acceptor.reject();
Expand Down
4 changes: 2 additions & 2 deletions test/test_destructors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ async function test(factory: ConnectionFactory): Promise<void> {

export async function test_destructors(
factory: ConnectionFactory,
server: MutexServer<IActivation, null>,
server: MutexServer<IActivation>,
): Promise<void> {
let promises: Promise<void>[] = [];
const promises: Promise<void>[] = [];
for (let i: number = 0; i < 4; ++i) promises.push(test(factory));

await Promise.all(promises);
Expand Down

0 comments on commit d027b4a

Please sign in to comment.