mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Migrate resolver from lambda to container
This commit is contained in:
5
cmd/resolver/.dockerignore
Normal file
5
cmd/resolver/.dockerignore
Normal file
@ -0,0 +1,5 @@
|
||||
.idea/
|
||||
.DS_Store/
|
||||
venv/
|
||||
package/
|
||||
__pycache__/
|
1
cmd/resolver/.gitignore
vendored
1
cmd/resolver/.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
.idea/
|
||||
venv/
|
||||
package/
|
||||
__pycache__/
|
||||
|
||||
function.zip
|
14
cmd/resolver/Dockerfile
Normal file
14
cmd/resolver/Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
FROM python:alpine3.7
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
|
||||
RUN apk add --virtual deps --no-cache build-base && \
|
||||
pip3 install --no-cache-dir --requirement requirements.txt --target /app && \
|
||||
apk del deps && \
|
||||
addgroup -S app && adduser -S app -G app
|
||||
|
||||
USER app
|
||||
|
||||
ENTRYPOINT ["python3", "-m", "sanic", "server.app", "--host", "0.0.0.0", "--port", "8080"]
|
||||
CMD ["--workers", "1"]
|
@ -9,7 +9,7 @@ deploy: build
|
||||
--function-name Resolver \
|
||||
--role $(shell aws --profile Podsync iam get-role --role-name PodsyncResolverLambdaRole --query 'Role.Arn' --output text) \
|
||||
--runtime python3.7 \
|
||||
--handler function.handler \
|
||||
--handler lambda.handler \
|
||||
--zip-file fileb://function.zip \
|
||||
--timeout 10 \
|
||||
--memory-size 128
|
||||
@ -19,7 +19,13 @@ update: build
|
||||
--function-name Resolver \
|
||||
--zip-file fileb://function.zip
|
||||
|
||||
.PHONY: push
|
||||
push:
|
||||
docker build -t mxpv/resolver .
|
||||
docker push mxpv/resolver
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf package function.zip
|
||||
|
||||
.PHONY: deploy update clean
|
||||
.PHONY: deploy update clean
|
||||
|
46
cmd/resolver/lambda.py
Normal file
46
cmd/resolver/lambda.py
Normal file
@ -0,0 +1,46 @@
|
||||
from resolver import *
|
||||
|
||||
|
||||
def handler(event, lambda_context):
|
||||
try:
|
||||
feed_id, video_id = _get_ids(event.get('path'))
|
||||
redirect_url = download(feed_id, video_id)
|
||||
return {
|
||||
'statusCode': 302,
|
||||
'statusDescription': '302 Found',
|
||||
'headers': {
|
||||
'Location': redirect_url,
|
||||
}
|
||||
}
|
||||
except QuotaExceeded:
|
||||
return {
|
||||
'statusCode': 429,
|
||||
'statusDescription': '429 Too Many Requests',
|
||||
'body': 'Too many requests. Daily limit is 1000. Consider upgrading account to get unlimited access',
|
||||
'headers': {'Content-Type': 'text/plain'}
|
||||
}
|
||||
|
||||
|
||||
def _get_ids(path):
|
||||
if not path or not path.startswith('/download'):
|
||||
raise InvalidUsage('Invalid path')
|
||||
|
||||
sections = path.split('/')
|
||||
|
||||
# >>> '/download/feed/video.xml'.split('/', 3)
|
||||
# ['', 'download', 'feed', 'video.xml']
|
||||
if len(sections) != 4:
|
||||
raise InvalidUsage('Invalid path')
|
||||
|
||||
feed_id = sections[2]
|
||||
video_id = sections[3]
|
||||
|
||||
if not feed_id or not video_id:
|
||||
raise InvalidUsage('Invalid feed or video id')
|
||||
|
||||
# Trim extension
|
||||
# >>> os.path.splitext('video.xml')[0]
|
||||
# 'video'
|
||||
video_id = os.path.splitext(video_id)[0]
|
||||
|
||||
return feed_id, video_id
|
@ -1 +1,3 @@
|
||||
youtube_dl==2019.04.24
|
||||
youtube_dl==2019.04.24
|
||||
sanic==18.12
|
||||
boto3==1.9.151
|
||||
|
@ -17,8 +17,8 @@ class QuotaExceeded(Exception):
|
||||
|
||||
dynamodb = boto3.resource('dynamodb')
|
||||
|
||||
feeds_table = dynamodb.Table(os.getenv('RESOLVER_DYNAMO_FEEDS_TABLE', 'Feeds'))
|
||||
counter_table = dynamodb.Table(os.getenv('RESOLVER_DYNAMO_RESOLVE_COUNTERS_TABLE', 'ResolveCounters'))
|
||||
feeds_table = dynamodb.Table(os.getenv('DYNAMO_FEEDS_TABLE_NAME', 'Feeds'))
|
||||
counter_table = dynamodb.Table(os.getenv('DYNAMO_RESOLVE_COUNTERS_TABLE', 'ResolveCounters'))
|
||||
|
||||
opts = {
|
||||
'quiet': True,
|
||||
@ -36,51 +36,6 @@ url_formats = {
|
||||
}
|
||||
|
||||
|
||||
def handler(event, lambda_context):
|
||||
try:
|
||||
feed_id, video_id = _get_ids(event.get('path'))
|
||||
redirect_url = download(feed_id, video_id)
|
||||
return {
|
||||
'statusCode': 302,
|
||||
'statusDescription': '302 Found',
|
||||
'headers': {
|
||||
'Location': redirect_url,
|
||||
}
|
||||
}
|
||||
except QuotaExceeded:
|
||||
return {
|
||||
'statusCode': 429,
|
||||
'statusDescription': '429 Too Many Requests',
|
||||
'body': 'Too many requests. Daily limit is 1000. Consider upgrading account to get unlimited access',
|
||||
'headers': {'Content-Type': 'text/plain'}
|
||||
}
|
||||
|
||||
|
||||
def _get_ids(path):
|
||||
if not path or not path.startswith('/download'):
|
||||
raise InvalidUsage('Invalid path')
|
||||
|
||||
sections = path.split('/')
|
||||
|
||||
# >>> '/download/feed/video.xml'.split('/', 3)
|
||||
# ['', 'download', 'feed', 'video.xml']
|
||||
if len(sections) != 4:
|
||||
raise InvalidUsage('Invalid path')
|
||||
|
||||
feed_id = sections[2]
|
||||
video_id = sections[3]
|
||||
|
||||
if not feed_id or not video_id:
|
||||
raise InvalidUsage('Invalid feed or video id')
|
||||
|
||||
# Trim extension
|
||||
# >>> os.path.splitext('video.xml')[0]
|
||||
# 'video'
|
||||
video_id = os.path.splitext(video_id)[0]
|
||||
|
||||
return feed_id, video_id
|
||||
|
||||
|
||||
def download(feed_id, video_id):
|
||||
if not feed_id:
|
||||
raise InvalidUsage('Invalid feed id')
|
||||
|
27
cmd/resolver/server.py
Normal file
27
cmd/resolver/server.py
Normal file
@ -0,0 +1,27 @@
|
||||
import resolver
|
||||
|
||||
from sanic import Sanic, response
|
||||
from sanic.exceptions import ServerError, InvalidUsage
|
||||
|
||||
app = Sanic()
|
||||
|
||||
|
||||
@app.get('/download/<feed_id>/<video_id>')
|
||||
async def download(req, feed_id, video_id):
|
||||
try:
|
||||
redirect_url = resolver.download(feed_id, video_id)
|
||||
return response.redirect(redirect_url)
|
||||
except resolver.InvalidUsage:
|
||||
raise InvalidUsage()
|
||||
except resolver.QuotaExceeded:
|
||||
raise ServerError('Too many requests. Daily limit is 1000. Consider upgrading account to get unlimited access.',
|
||||
status_code=429)
|
||||
|
||||
|
||||
@app.get('/ping')
|
||||
async def ping(req):
|
||||
return response.text('pong')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=8080)
|
@ -38,3 +38,14 @@ services:
|
||||
restart: always
|
||||
ports:
|
||||
- 8081:80
|
||||
resolver:
|
||||
image: mxpv/resolver:latest
|
||||
container_name: resolver
|
||||
command: --workers 8
|
||||
restart: always
|
||||
ports:
|
||||
- 8082:8080
|
||||
environment:
|
||||
- AWS_DEFAULT_REGION=us-east-1
|
||||
- DYNAMO_FEEDS_TABLE_NAME=Prod_Feeds
|
||||
- DYNAMO_RESOLVE_COUNTERS_TABLE=Prod_ResolveCounters
|
||||
|
Reference in New Issue
Block a user