mirror of https://github.com/kern/filepizza
Begin redis channel impl
parent
6a0ab981f0
commit
e70445530d
@ -1,23 +1,11 @@
|
||||
version: '3'
|
||||
services:
|
||||
filepizza:
|
||||
image: kern/filepizza:latest
|
||||
restart: always
|
||||
build:
|
||||
context: .
|
||||
redis:
|
||||
image: redis:latest
|
||||
ports:
|
||||
- 3333:3333
|
||||
environment:
|
||||
- PORT=3333
|
||||
- EXTRA_ICE_SERVERS=turn:localhost:3478
|
||||
- WEBTORRENT_TRACKERS=ws://localhost:8000
|
||||
coturn:
|
||||
image: instrumentisto/coturn:latest
|
||||
network_mode: host
|
||||
ports:
|
||||
- 3478:3478
|
||||
bittorrent-tracker:
|
||||
image: henkel/bittorrent-tracker:latest
|
||||
command: ["npx", "bittorrent-tracker", "--http-hostname", "0.0.0.0", "--ws"]
|
||||
ports:
|
||||
- 8000:8000
|
||||
- 6379:6379
|
||||
# coturn:
|
||||
# image: instrumentisto/coturn:latest
|
||||
# network_mode: host
|
||||
# ports:
|
||||
# - 3478:3478
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
import config from './config'
|
||||
import Redis from 'ioredis'
|
||||
|
||||
export type Channel = {
|
||||
uploaderPeerID: string
|
||||
longSlug: string
|
||||
shortSlug: string
|
||||
}
|
||||
|
||||
export interface ChannelRepo {
|
||||
create(uploaderPeerID: string, ttl?: number): Promise<Channel>
|
||||
fetch(slug: string): Promise<Channel | null>
|
||||
renew(slug: string, ttl: number): Promise<void>
|
||||
destroy(slug: string): Promise<void>
|
||||
}
|
||||
|
||||
export class RedisChannelRepo implements ChannelRepo {
|
||||
client: Redis.Redis
|
||||
|
||||
constructor(redisURL: string) {
|
||||
this.client = new Redis(redisURL)
|
||||
}
|
||||
|
||||
async create(
|
||||
uploaderPeerID: string,
|
||||
ttl: number = config.channel.ttl,
|
||||
): Promise<Channel> {
|
||||
const shortSlug = await this.generateShortSlug()
|
||||
const longSlug = await this.generateLongSlug()
|
||||
|
||||
const channel: Channel = {
|
||||
uploaderPeerID,
|
||||
longSlug,
|
||||
shortSlug,
|
||||
}
|
||||
const channelStr = this.serializeChannel(channel)
|
||||
|
||||
await this.client.setex(this.getLongSlugKey(longSlug), ttl, channelStr)
|
||||
await this.client.setex(this.getShortSlugKey(shortSlug), ttl, channelStr)
|
||||
|
||||
return channel
|
||||
}
|
||||
|
||||
async fetch(slug: string): Promise<Channel | null> {
|
||||
const shortChannelStr = await this.client.get(this.getShortSlugKey(slug))
|
||||
if (shortChannelStr) {
|
||||
return this.deserializeChannel(shortChannelStr)
|
||||
}
|
||||
|
||||
const longChannelStr = await this.client.get(this.getLongSlugKey(slug))
|
||||
if (longChannelStr) {
|
||||
return this.deserializeChannel(longChannelStr)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
async renew(slug: string, ttl: number = config.channel.ttl): Promise<void> {
|
||||
const channel = await this.fetch(slug)
|
||||
if (!channel) {
|
||||
return
|
||||
}
|
||||
|
||||
await this.client.expire(this.getShortSlugKey(channel.shortSlug), ttl)
|
||||
await this.client.expire(this.getLongSlugKey(channel.longSlug), ttl)
|
||||
}
|
||||
|
||||
async destroy(slug: string): Promise<void> {
|
||||
const channel = await this.fetch(slug)
|
||||
if (!channel) {
|
||||
return
|
||||
}
|
||||
|
||||
await this.client.del(channel.longSlug)
|
||||
await this.client.del(channel.shortSlug)
|
||||
}
|
||||
|
||||
private async generateShortSlug(): Promise<string> {
|
||||
return 'foo' // TODO
|
||||
}
|
||||
|
||||
private async generateLongSlug(): Promise<string> {
|
||||
return 'foo/bar/baz' // TODO
|
||||
}
|
||||
|
||||
private getShortSlugKey(shortSlug: string): string {
|
||||
return `short:${shortSlug}`
|
||||
}
|
||||
|
||||
private getLongSlugKey(longSlug: string): string {
|
||||
return `long:${longSlug}`
|
||||
}
|
||||
|
||||
private serializeChannel(channel: Channel): string {
|
||||
return JSON.stringify(channel)
|
||||
}
|
||||
|
||||
private deserializeChannel(str: string): Channel {
|
||||
return JSON.parse(str) as Channel
|
||||
}
|
||||
}
|
||||
|
||||
export const channelRepo = new RedisChannelRepo(config.redisURL)
|
||||
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
redisURL: 'redis://localhost:6379/0',
|
||||
channel: {
|
||||
ttl: 60 * 60, // 1 hour
|
||||
},
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import type { Request, Response } from 'express'
|
||||
import { channelRepo } from '../../channel'
|
||||
|
||||
export default (req: Request, res: Response): void => {
|
||||
// TODO: validate method and uploaderPeerID
|
||||
|
||||
channelRepo
|
||||
.create(req.body.uploaderPeerID)
|
||||
.then((channel) => {
|
||||
res.statusCode = 200
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify(channel))
|
||||
})
|
||||
.catch((err) => {
|
||||
res.statusCode = 500
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify({ error: err.toString() }))
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import type { Request, Response } from 'express'
|
||||
import { channelRepo } from '../../channel'
|
||||
|
||||
export default (req: Request, res: Response): void => {
|
||||
// TODO: validate method and slug
|
||||
|
||||
channelRepo
|
||||
.destroy(req.body.slug)
|
||||
.then((channel) => {
|
||||
res.statusCode = 200
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify(channel))
|
||||
})
|
||||
.catch((err) => {
|
||||
res.statusCode = 500
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify({ error: err.toString() }))
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import type { Request, Response } from 'express'
|
||||
import { channelRepo } from '../../channel'
|
||||
|
||||
export default (req: Request, res: Response): void => {
|
||||
// TODO: validate method and slug
|
||||
|
||||
channelRepo
|
||||
.renew(req.body.slug)
|
||||
.then((channel) => {
|
||||
res.statusCode = 200
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify(channel))
|
||||
})
|
||||
.catch((err) => {
|
||||
res.statusCode = 500
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify({ error: err.toString() }))
|
||||
})
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
const { createServer } = require('http')
|
||||
const { parse } = require('url')
|
||||
const next = require('next')
|
||||
const PeerDataServer = require('peer-data-server')
|
||||
|
||||
const appendPeerDataServer = PeerDataServer.default || PeerDataServer
|
||||
const dev = process.env.NODE_ENV !== 'production'
|
||||
const app = next({ dev })
|
||||
const handle = app.getRequestHandler()
|
||||
|
||||
app.prepare().then(() => {
|
||||
const server = createServer((req, res) => {
|
||||
const parsedUrl = parse(req.url, true)
|
||||
handle(req, res, parsedUrl)
|
||||
})
|
||||
|
||||
appendPeerDataServer(server)
|
||||
|
||||
server.listen(3000, (err) => {
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
|
||||
console.log('> Ready on http://localhost:3000')
|
||||
})
|
||||
})
|
||||
Loading…
Reference in New Issue