112 lines
3.9 KiB
Python
112 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
import io
|
|
from datetime import datetime
|
|
import tzlocal
|
|
from xeger import Xeger
|
|
from flask_restful import Resource
|
|
from flask import request, current_app, abort
|
|
from magic_amqp import magic_amqp
|
|
from influxus import influx_db
|
|
from schemas import SampleSchema
|
|
from redis_client import redis_client
|
|
import opentracing
|
|
|
|
"""
|
|
Flask Restful endpoints
|
|
"""
|
|
|
|
__author__ = '@tormakris'
|
|
__copyright__ = "Copyright 2020, Birbnetes Team"
|
|
__module_name__ = "endpoints"
|
|
__version__text__ = "1"
|
|
|
|
|
|
class SampleResource(Resource):
|
|
"""
|
|
Sample endpoint
|
|
See: https://swagger.kmlabz.com/?urls.primaryName=Input%20Service
|
|
"""
|
|
|
|
sampleschema = SampleSchema(many=False)
|
|
|
|
def post(self):
|
|
"""
|
|
Post request send to the endpoint
|
|
:return:
|
|
"""
|
|
with opentracing.tracer.start_active_span('parseAndValidate'):
|
|
if 'file' not in request.files:
|
|
return abort(400, "no file found")
|
|
else:
|
|
soundfile = request.files['file']
|
|
|
|
if 'description' not in request.form:
|
|
return abort(400, "no description found")
|
|
else:
|
|
description_raw = request.form.get("description")
|
|
|
|
if soundfile.content_type != 'audio/wave':
|
|
current_app.logger.info(f"Input file was not WAV.")
|
|
return abort(415, 'Input file not a wave file.')
|
|
try:
|
|
desc = self.sampleschema.loads(description_raw)
|
|
except Exception as e:
|
|
current_app.logger.exception(e)
|
|
return abort(417, 'Input JSON schema invalid')
|
|
|
|
with opentracing.tracer.start_active_span('generateTag'):
|
|
xeger = Xeger(limit=30)
|
|
while True:
|
|
generated_tag = xeger.xeger(r'^[a-zA-Z]+[0-9a-zA-Z_]*$')[:32]
|
|
if len(generated_tag) > 2: # Ensure minimum length
|
|
break
|
|
|
|
with opentracing.tracer.start_active_span('publishMetaMessage'):
|
|
try: # TODO change exchange
|
|
magic_amqp.publish(
|
|
{
|
|
'tag': generated_tag,
|
|
'timestamp': datetime.now().isoformat(),
|
|
'device_id': desc['device_id'],
|
|
'device_date': desc['date'].isoformat()
|
|
}
|
|
)
|
|
except Exception as e:
|
|
current_app.logger.exception(e)
|
|
return abort(500, f"AMQP Publish error: {str(e)}")
|
|
|
|
with opentracing.tracer.start_active_span('readSampleToMemory'):
|
|
buf = io.BytesIO()
|
|
soundfile.save(buf)
|
|
|
|
with opentracing.tracer.start_active_span('putToCache'):
|
|
redis_client.set(generated_tag, buf.getbuffer()) # getbuffer is quick as it does not copy like getvalue
|
|
|
|
# Announce only after the data is successfully committed
|
|
with opentracing.tracer.start_active_span('publishInCacheMessage'):
|
|
try: # TODO change exchange
|
|
magic_amqp.publish({'tag': generated_tag})
|
|
except Exception as e:
|
|
current_app.logger.exception(e)
|
|
return abort(500, f"AMQP Publish error: {str(e)}")
|
|
|
|
# metrics
|
|
if current_app.config['ENABLE_INFLUXDB']:
|
|
with opentracing.tracer.start_active_span('influxdb.write_points'):
|
|
influx_db.write_points(
|
|
[
|
|
{
|
|
'time': datetime.now(tz=tzlocal.get_localzone()),
|
|
'measurement': 'cloudinput',
|
|
'tags': {
|
|
'device': desc['device_id']
|
|
},
|
|
'fields': {
|
|
'bruh': 1.0
|
|
}
|
|
}
|
|
]
|
|
)
|
|
|
|
return {"tag": generated_tag}, 200
|