Skip to content

Commit 639cb00

Browse files
committed
Initial version
1 parent 3733dfc commit 639cb00

File tree

141 files changed

+20697
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+20697
-0
lines changed

.editorconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[*.go]
2+
indent_style = tab
3+
4+
[*.{ts,tsx,json,md,yml}]
5+
indent_style = space
6+
indent_size = 2
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Server Release
2+
on:
3+
push:
4+
tags:
5+
- 'v*'
6+
7+
jobs:
8+
build:
9+
name: Create Release
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- uses: actions/setup-go@v2
14+
with:
15+
go-version: '1.15.5'
16+
- name: Build
17+
run: |
18+
go get
19+
go get github.com/Songmu/gocredits/cmd/gocredits
20+
make build
21+
working-directory: server
22+
23+
# https://zenn.dev/seita/articles/d1dba77043be8fd50eeb
24+
- name: Get the version
25+
id: get_version
26+
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
27+
- name: Get commit summary
28+
id: get_commit_summary
29+
run: |
30+
PREVIOUS_TAG=$(git tag --sort=-creatordate | sed -n 2p)
31+
echo "PREVIOUS_TAG: $PREVIOUS_TAG"
32+
COMMIT_SUMMARY="$(git log --oneline --pretty=tformat:"%h %s" $PREVIOUS_TAG..${{ github.ref }})"
33+
COMMIT_SUMMARY="${COMMIT_SUMMARY//$'\n'/'%0A'}"
34+
echo ::set-output name=COMMIT_SUMMARY::$COMMIT_SUMMARY
35+
36+
- id: create_release
37+
uses: actions/create-release@v1
38+
env:
39+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
with:
41+
tag_name: ${{ github.ref }}
42+
release_name: Release ${{ github.ref }}
43+
body: ${{ steps.get_commit_summary.outputs.COMMIT_SUMMARY }}
44+
draft: true
45+
prerelease: true
46+
- uses: actions/upload-release-asset@v1
47+
env:
48+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49+
with:
50+
upload_url: ${{ steps.create_release.outputs.upload_url }}
51+
asset_path: ./server/dsps.zip
52+
asset_name: dsps.zip
53+
asset_content_type: application/zip

.github/workflows/server-test.yaml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Server Test
2+
on: push
3+
4+
jobs:
5+
lint:
6+
strategy:
7+
matrix:
8+
go-version: [ '1.15.5' ]
9+
name: lint
10+
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v2
15+
- uses: actions/setup-go@v2
16+
with:
17+
go-version: ${{ matrix.go-version }}
18+
- name: golangci-lint
19+
uses: golangci/golangci-lint-action@v2
20+
with:
21+
version: v1.33.0
22+
working-directory: server
23+
- name: Other Lint
24+
shell: bash
25+
working-directory: server
26+
run: |
27+
go mod download
28+
make lint
29+
- name: Update Go Report Card
30+
if: github.ref == 'refs/heads/main'
31+
shell: bash
32+
working-directory: server
33+
run: curl -X POST -F "repo=github.com/$GITHUB_REPOSITORY" https://goreportcard.com/checks
34+
35+
test:
36+
strategy:
37+
matrix:
38+
redis-version: [ '6.0.9' ]
39+
go-version: [ '1.15.5' ]
40+
name: test redis:${{ matrix.redis-version }} go:${{ matrix.go-version }}
41+
42+
runs-on: ubuntu-latest
43+
container: golang:${{ matrix.go-version }}-buster
44+
45+
services:
46+
redis:
47+
image: redis:${{ matrix.redis-version }}
48+
ports:
49+
- 6379:6379
50+
options: >-
51+
--health-cmd "redis-cli ping"
52+
--health-interval 3s
53+
--health-timeout 5s
54+
--health-retries 10
55+
56+
steps:
57+
- uses: actions/checkout@v2
58+
- uses: actions/setup-go@v2
59+
with:
60+
go-version: ${{ matrix.go-version }}
61+
- name: Test
62+
shell: bash
63+
working-directory: server
64+
run: make test
65+
- name: Upload to codecov
66+
if: github.ref == 'refs/heads/main'
67+
shell: bash
68+
working-directory: server
69+
run: |
70+
curl -s https://codecov.io/bash > codecov.sh
71+
bash codecov.sh
72+
- uses: actions/upload-artifact@v2
73+
with:
74+
name: coverage.html
75+
path: server/coverage.html

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# DSPS - Durable & Simple PubSub
2+
3+
[![MIT License](https://img.shields.io/badge/LICENSE-MIT-brightgreen)](./LICENSE)
4+
[![Server Test](https://github.com/saiya/dsps/workflows/Server%20Test/badge.svg?1)](https://github.com/saiya/dsps/actions?query=workflow%3A%22Server+Test%22)
5+
[![Codecov](https://codecov.io/gh/saiya/dsps/branch/main/graph/badge.svg?token=DSSOWMB60X)](https://codecov.io/gh/saiya/dsps)
6+
[![Go Report Card](https://goreportcard.com/badge/github.com/saiya/dsps?1)](https://goreportcard.com/report/github.com/saiya/dsps)
7+
8+
DSPS is a PubSub system that provides following advantages:
9+
10+
- Durable message passing (no misfire)
11+
- Simple messaging interface (even `curl` is enough to communicate with the DSPS server)
12+
13+
DSPS supports message buffering, resending, deduplication, ordering, etc. to secure your precious messages.
14+
15+
DSPS server supports intuitive interfaces such as HTTP short polling, long polling, outgoing webhook, etc.
16+
17+
Note that DSPS does **NOT** aim to provide followings:
18+
19+
- Very low latency message passing
20+
- DSPS suppose milliseconds latency tolerant use-case
21+
- Too massive message flow rate comparing to your storage spec
22+
- DSPS temporary stores messages to resend message
23+
- Warehouse to keep long-living message
24+
- DSPS aim to provide message passing, not archiving message
25+
26+
27+
# 3 minutes to getting started with DSPS
28+
29+
```sh
30+
# Get binary from https://github.com/saiya/dsps/releases
31+
curl -o dsps.zip -s https://api.github.com/repos/saiya/dsps/releases | jq -r ".[0].assets[] | select(.name | test(\"dsps.zip\")) | .browser_download_url"
32+
unzip dsps.zip
33+
cp dsps/dsps-$(uname -o)-$(uname -m) ./dsps
34+
chmod +x dsps
35+
36+
# Launch DSPS server (you can choose any port number).
37+
./dsps --port 3099
38+
39+
#
40+
# ... Open another terminal window to run following tutorial ...
41+
#
42+
43+
CHANNEL="my-channel"
44+
SUBSCRIBER="my-subscriber"
45+
46+
# Create a HTTP polling subscriber.
47+
curl -w "\n" -X PUT "http://localhost:3099/channel/${CHANNEL}/subscription/polling/${SUBSCRIBER}"
48+
49+
# Publish message to the channel.
50+
curl -w "\n" -X PUT -H "Content-Type: application/json" \
51+
-d '{ "hello": "Hi!" }' \
52+
"http://localhost:3099/channel/${CHANNEL}/message/my-first-message"
53+
54+
# Receive messages with HTTP long-polling.
55+
# In this example, this API immediately returns
56+
# because the subscriber already have been received a message.
57+
curl -w "\n" -X GET "http://localhost:3099/channel/${CHANNEL}/subscription/polling/${SUBSCRIBER}?timeout=60s&max=64"
58+
59+
ACK_HANDLE="<< set string returned in the above API response >>"
60+
61+
# Cleanup received messages from the subscriber.
62+
curl -i -X DELETE \
63+
"http://localhost:3099/channel/${CHANNEL}/subscription/polling/${SUBSCRIBER}/message?ackHandle=${ACK_HANDLE}"
64+
```
65+
66+
Tips: see [server interface documentation](./server/doc/interface) for more API interface detail.
67+
68+
## Message resending - you have to DELETE received messages
69+
70+
You may notice that your receive same messages every time you GET the subscriber endpoint. Because DSPS resend messages until you explicitly delete it to prevent message loss due to network/client error.
71+
72+
The way to delete message depends on the [subscriber type](./server/doc/interface/subscribe/README.md). For example, HTTP polling subscriber (used in above example) supports HTTP DELETE method to remove messages from the subscriber.
73+
74+
# To know more
75+
76+
- [Detail of the DSPS server](./server/README.md)
77+
- Before running DSPS in production, recommend to look this document
78+
- [API interface of the DSPS server](./server/doc/interface)
79+
- [JavaScript / TypeScript client](./client/js/README.md)
80+
- [Security & Authentication](./server/doc/security.md)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"/Users/seiya.yazaki/work/github.com/saiya/dsps/client/js-sample-chat-client/src/App.tsx":"1","/Users/seiya.yazaki/work/github.com/saiya/dsps/client/js-sample-chat-client/src/model/index.ts":"2","/Users/seiya.yazaki/work/github.com/saiya/dsps/client/js-sample-chat-client/src/ChannelView.tsx":"3"},{"size":5207,"mtime":1606769613130,"results":"4","hashOfConfig":"5"},{"size":3142,"mtime":1606772455836,"results":"6","hashOfConfig":"5"},{"size":2383,"mtime":1606772285700,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"ewyf55",{"filePath":"10","messages":"11","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/seiya.yazaki/work/github.com/saiya/dsps/client/js-sample-chat-client/src/App.tsx",[],"/Users/seiya.yazaki/work/github.com/saiya/dsps/client/js-sample-chat-client/src/model/index.ts",[],"/Users/seiya.yazaki/work/github.com/saiya/dsps/client/js-sample-chat-client/src/ChannelView.tsx",[]]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# DSPS JS client sample App
2+
3+
## How to run
4+
5+
1. `yarn --cwd ../js install`
6+
2. `yarn --cwd ../js link`
7+
3. `yarn --cwd ../js build`
8+
4. `yarn link @dsps/client`
9+
5. `yarn install`
10+
6. Start [dsps server](../../server) in port 3000
11+
- e.g. `go run main.go` in the `../../server` directory
12+
7. Start this app with `yarn start`
13+
- It opens [http://localhost:3001](http://localhost:3001) in your browser.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "js-sample-chat-client",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@dsps/client": "../js",
7+
"@material-ui/core": "^4.11.1",
8+
"@material-ui/icons": "^4.9.1",
9+
"@material-ui/lab": "^4.0.0-alpha.56",
10+
"@testing-library/jest-dom": "^5.11.4",
11+
"@testing-library/react": "^11.1.0",
12+
"@testing-library/user-event": "^12.1.10",
13+
"@types/jest": "^26.0.15",
14+
"@types/node": "^12.0.0",
15+
"@types/react": "^16.9.53",
16+
"@types/react-dom": "^16.9.8",
17+
"react": "^17.0.1",
18+
"react-dom": "^17.0.1",
19+
"react-scripts": "4.0.1",
20+
"typescript": "^4.0.3",
21+
"web-vitals": "^0.2.4"
22+
},
23+
"scripts": {
24+
"start": "PORT=3001 react-scripts start",
25+
"build": "react-scripts build",
26+
"test": "react-scripts test",
27+
"eject": "react-scripts eject"
28+
},
29+
"proxy": "http://localhost:3000",
30+
"eslintConfig": {
31+
"extends": [
32+
"react-app",
33+
"react-app/jest"
34+
]
35+
},
36+
"browserslist": {
37+
"production": [
38+
">0.2%",
39+
"not dead",
40+
"not op_mini all"
41+
],
42+
"development": [
43+
"last 1 chrome version",
44+
"last 1 firefox version",
45+
"last 1 safari version"
46+
]
47+
}
48+
}
3.78 KB
Binary file not shown.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta
9+
name="description"
10+
content="Web site created using create-react-app"
11+
/>
12+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13+
<!--
14+
manifest.json provides metadata used when your web app is installed on a
15+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16+
-->
17+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
18+
<!--
19+
Notice the use of %PUBLIC_URL% in the tags above.
20+
It will be replaced with the URL of the `public` folder during the build.
21+
Only files inside the `public` folder can be referenced from the HTML.
22+
23+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24+
work correctly both with client-side routing and a non-root public URL.
25+
Learn how to configure a non-root public URL by running `npm run build`.
26+
-->
27+
<title>React App</title>
28+
</head>
29+
<body>
30+
<noscript>You need to enable JavaScript to run this app.</noscript>
31+
<div id="root"></div>
32+
<!--
33+
This HTML file is a template.
34+
If you open it directly in the browser, you will see an empty page.
35+
36+
You can add webfonts, meta tags, or analytics to this file.
37+
The build step will place the bundled scripts into the <body> tag.
38+
39+
To begin the development, run `npm start` or `yarn start`.
40+
To create a production bundle, use `npm run build` or `yarn build`.
41+
-->
42+
</body>
43+
</html>

0 commit comments

Comments
 (0)