1
0
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:
Maksym Pavlenko
2019-05-17 22:55:21 -07:00
parent f1192a948c
commit c5473e3bba
9 changed files with 117 additions and 50 deletions

View File

@ -0,0 +1,5 @@
.idea/
.DS_Store/
venv/
package/
__pycache__/

View File

@ -1,5 +1,6 @@
.idea/
venv/
package/
__pycache__/
function.zip

14
cmd/resolver/Dockerfile Normal file
View 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"]

View File

@ -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
View 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

View File

@ -1 +1,3 @@
youtube_dl==2019.04.24
youtube_dl==2019.04.24
sanic==18.12
boto3==1.9.151

View File

@ -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
View 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)

View File

@ -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