Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Jannchie committed Mar 19, 2021
0 parents commit cdc690c
Show file tree
Hide file tree
Showing 9 changed files with 4,028 additions and 0 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: CI Pipeline

# trigger build when pushing, or when creating a pull request
on: [push, pull_request]

jobs:
build:
# run build on latest ubuntu
runs-on: ubuntu-latest
steps:
# this will check out the current branch (https://github.com/actions/checkout#Push-a-commit-using-the-built-in-token)
- uses: actions/checkout@v2
# installing Node
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
# this will use the latest Node 12 version
node-version: 12.x
# install dependencies using clean install to avoid package lock updates
- run: yarn install
# finally run the tests
- run: yarn coverage
# Save coverage report in Coveralls
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
108 changes: 108 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
lib
.vscode
node_modules

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port
.coveralls.yml
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# jsemaphore

[![Coverage Status](https://coveralls.io/repos/github/Jannchie/jsemaphore/badge.svg?branch=main)](https://coveralls.io/github/Jannchie/jsemaphore?branch=main) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/Jannchie/jsemaphore.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Jannchie/jsemaphore/context:javascript)

## Usage

``` ts
import { parseCookies, stringifyCookies } from "jsemaphore";
cookies = "test=value; name=jsemaphore";
let cookiesMap = parseCookies(cookies);
cookiesMap.set("test", "new_value");
const cookiesString = stringifyCookies(cookiesMap);

// jest
expect(cookiesString).toBe("test=new_value; name=jsemaphore");
```
7 changes: 7 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
roots: ["<rootDir>"],
transform: {
"^.+\\.(ts|tsx)$": "ts-jest",
},
testTimeout: 5000,
};
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "jsemaphore",
"version": "1.0.0",
"description": "Simple semaphore, just like semaphore in python.",
"main": "lib/index.js",
"repository": "https://github.com/Jannchie/spider-cookies",
"author": "Jannchie <jannchie@gmail.com>",
"license": "MIT",
"typings": "typings",
"scripts": {
"coveralls": "jest --coverage && cat ./coverage/lcov.info | coveralls",
"coverage": "jest --coverage"
},
"devDependencies": {
"@types/jest": "^26.0.21",
"coveralls": "^3.1.0",
"jest": "^26.6.3",
"ts-jest": "^26.5.4",
"typescript": "^4.2.3"
},
"keywords": [
"semaphore"
]
}
35 changes: 35 additions & 0 deletions src/semaphore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
type PromiseInfo = {
resolve: (value: unknown) => void;
reject: (reason?: any) => void;
};
export class Semaphore {
private count: number;
private concurrency: number;
private waitingTasks: PromiseInfo[];
constructor(concurrency: number) {
if (concurrency <= 0) {
throw new Error("Concurrency Should greater then 0!");
}
this.count = 0;
this.concurrency = concurrency;
this.waitingTasks = [];
}
async acquire() {
if (this.concurrency > this.count) {
this.count++;
return;
} else {
return new Promise((resolve, reject) => {
this.waitingTasks.push({ resolve, reject });
});
}
}
release() {
this.count--;
if (this.waitingTasks.length > 0 && this.count < this.concurrency) {
this.count++;
let promise = this.waitingTasks.shift()!;
promise.resolve(null);
}
}
}
61 changes: 61 additions & 0 deletions test/semaphore.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Semaphore } from "../src/semaphore";

test("error", () => {
expect(() => {
new Semaphore(-1);
}).toThrow("Concurrency Should greater then 0!");
expect(() => {
new Semaphore(0);
}).toThrow("Concurrency Should greater then 0!");
});

test("base concurrency", async () => {
async function task(s: Semaphore) {
await new Promise((resolve) => setTimeout(() => resolve(null), 1000));
s.release();
}
const s = new Semaphore(1);
const start = performance.now();
const tasks = new Array<Promise<void>>();
for (let i = 0; i < 2; i++) {
await s.acquire();
tasks.push(task(s));
}
await Promise.all(tasks);
const end = performance.now();
expect(end - start).toBeGreaterThan(2000);
});

test("useless concurrency", async () => {
async function task(s: Semaphore) {
await new Promise((resolve) => setTimeout(() => resolve(null), 1000));
s.release();
}
const s = new Semaphore(10);
const start = performance.now();
const tasks = new Array<Promise<void>>();
for (let i = 0; i < 5; i++) {
await s.acquire();
tasks.push(task(s));
}
await Promise.all(tasks);
const end = performance.now();
expect(end - start).toBeLessThan(2000);
});

test("concurrency", async () => {
async function task(s: Semaphore) {
await new Promise((resolve) => setTimeout(() => resolve(null), 1000));
s.release();
}
const s = new Semaphore(10);
const start = performance.now();
const tasks = new Array<Promise<void>>();
for (let i = 0; i < 40; i++) {
await s.acquire();
tasks.push(task(s));
}
await Promise.all(tasks);
const end = performance.now();
expect(end - start).toBeGreaterThan(4000);
});
31 changes: 31 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"compilerOptions": {
"outDir": "lib",
"declarationDir": "typings",
"target": "es5",
"declarationMap": false,
"declaration": true,
"inlineSourceMap": true,
"moduleResolution": "Node",
"allowUmdGlobalAccess": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"allowJs": true,
"skipLibCheck": true,
"downlevelIteration": true,
"strictNullChecks": true,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noImplicitAny": false,
"noUnusedLocals": false,
"allowUnreachableCode": false,
"disableSizeLimit": true,
"disableReferencedProjectLoad": true,
"extendedDiagnostics": true,
"noImplicitUseStrict": true,
"noImplicitThis": true
},
"compileOnSave": true,
"include": ["src/**/*"]
}
Loading

0 comments on commit cdc690c

Please sign in to comment.