diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..99a0f01 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +*.log +__pycache__/ +.env/ +.vscode +*.md +*.sqlite3 + +#migration +server/main/migrations \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6325bbb --- /dev/null +++ b/.gitignore @@ -0,0 +1,234 @@ +### Django ### +*.log +*.pot +*.pyc +__pycache__/ +local_settings.py +db.sqlite3 +media +media_files + +/static/ + +### Linux ### +*~ +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf +.idea/ + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Python ### +# Byte-compiled / optimized / DLL files +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo + +# Django stuff: + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +*.whl + +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +### Python Patch ### +.venv/ +.env +.vscode +### Python.VirtualEnv Stack ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +# [Ss]cripts +pyvenv.cfg +pip-selfcheck.json +\.vscode/ + +# not +src/main/test_app-data +handyscript \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0ac49b8 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +run-locust: + locust -f main/tests/test_locust.py -P 8090 + +remove-containers: + docker container prune -f + +docker-build: + docker-compose build + docker-compose rm -f + +docker-start: + docker-compose up + +docker-stop: + docker-compose down + +docker-cleanup: + docker-compose down -v \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b1b75ba --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# mcmanaman + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f64226d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,143 @@ +version: "3" + +services: + web: &basePy + build: + context: . + dockerfile: ./dockerfiles/py/Dockerfile + volumes: + - ./main:/main + - static_files:/static_files + - uploaded_files:/uploaded_files + env_file: + - ./dockerfiles/py/.app_env + depends_on: + - postgres + links: + - postgres + command: sh /appRun.sh + restart: unless-stopped + + faust: + <<: *basePy + + depends_on: + - web + - redis + - kafka + - kafka-create-topics + links: + - redis + - kafka + - kafka-create-topics + ports: + - "6066:6066" + command: sh /faustRun.sh + restart: unless-stopped + + locust_master: + image: locustio/locust + ports: + - "8089:8089" + expose: + - "8089" + volumes: + - ./main/tests:/mnt/locust + depends_on: + - nginx + command: -f /mnt/locust/test_locust.py --master -H http://nginx:8000 + + locust_worker: + image: locustio/locust + volumes: + - ./main/tests:/mnt/locust + depends_on: + - nginx + - locust_master + command: -f /mnt/locust/test_locust.py --worker --master-host locust_master + + postgres: + image: postgres + build: ./dockerfiles/postgresql/ + volumes: + - pgdata:/var/lib/postgresql/data/ + env_file: + - ./dockerfiles/postgresql/.pg_env + ports: + - "5432:5432" + expose: + - "5432" + restart: unless-stopped + + redis: + image: redis:5.0.5 + ports: + - "6385:6379" + expose: + - "6385" + command: ["redis-server", "--protected-mode", "no"] + hostname: redis + restart: unless-stopped + + nginx: + build: + context: . + dockerfile: ./dockerfiles/nginx/Dockerfile + ports: + - "8000:8000" + expose: + - "8000" + volumes: + - static_files:/static_files + - uploaded_files:/uploaded_files + depends_on: + - web + restart: unless-stopped + + zookeeper: + image: confluentinc/cp-zookeeper:5.2.0 + hostname: zookeeper + ports: + - "2181:2181" + expose: + - "2181" + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + restart: on-failure + + kafka: + image: confluentinc/cp-kafka:5.2.0 + hostname: kafka + ports: + - "9092:9092" + expose: + - "9092" + depends_on: + - zookeeper + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 + KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false" + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + restart: on-failure + + kafka-create-topics: + image: confluentinc/cp-kafka:5.2.0 + depends_on: + - kafka + hostname: kafka-create-topics + command: "bash -c 'echo Waiting for Kafka to be ready... && \ + cub kafka-ready -b kafka:9092 1 20 && \ + kafka-topics --create --topic test --if-not-exists --zookeeper zookeeper:2181 --partitions 1 --replication-factor 1 && \ + sleep infinity'" + environment: + KAFKA_BROKER_ID: ignored + KAFKA_ZOOKEEPER_CONNECT: ignored + restart: on-failure + +volumes: + pgdata: + static_files: + uploaded_files: diff --git a/dockerfiles/nginx/Dockerfile b/dockerfiles/nginx/Dockerfile new file mode 100644 index 0000000..79c7194 --- /dev/null +++ b/dockerfiles/nginx/Dockerfile @@ -0,0 +1,5 @@ +FROM nginx:latest + +RUN rm /etc/nginx/conf.d/default.conf + +COPY ./dockerfiles/nginx/default.conf /etc/nginx/conf.d/ \ No newline at end of file diff --git a/dockerfiles/nginx/default.conf b/dockerfiles/nginx/default.conf new file mode 100644 index 0000000..156f495 --- /dev/null +++ b/dockerfiles/nginx/default.conf @@ -0,0 +1,78 @@ +server { + listen 8000; + server_name localhost; + error_log /var/log/nginx/error.log; + access_log /var/log/nginx/access.log; + server_tokens off; + + location /static/ { + autoindex off; + alias /static_files/; + } + + + location / { + try_files $uri $uri/ @python; + } + + location @python { + proxy_pass http://web:5000; + proxy_pass_request_headers on; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect off; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + } +} + + + +# upstream backend { +# least_conn; +# server app:5000; +# } + +# server { + +# listen 8000; +# server_name localhost; +# error_log /var/log/nginx/error.log; +# access_log /var/log/nginx/access.log; +# server_tokens off; + +# location /static/ { +# autoindex off; +# alias /static_files/; +# } + +# # handle x-accel-redirect (with an alias to /uploaded_files/) +# location /uploads/ { +# internal; +# autoindex off; +# alias /uploaded_files/; + +# etag off; + +# # handle x-accel- headers +# add_header Content-Length $upstream_http_x_accel_content_length; +# add_header Last-Modified $upstream_http_x_accel_last_modified; +# add_header etag $upstream_http_x_accel_etag; +# } + +# location / { +# try_files $uri $uri/ @python_django; +# } + +# location @python_django { +# proxy_pass http://backend:8000; +# proxy_pass_request_headers on; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +# proxy_set_header Host $http_host; +# proxy_set_header X-Forwarded-Proto $scheme; +# proxy_redirect off; +# proxy_buffering off; +# } + +# } diff --git a/dockerfiles/postgresql/.pg_env b/dockerfiles/postgresql/.pg_env new file mode 100644 index 0000000..529f782 --- /dev/null +++ b/dockerfiles/postgresql/.pg_env @@ -0,0 +1,3 @@ +POSTGRES_USER=user +POSTGRES_PASSWORD=password +POSTGRES_DB=db \ No newline at end of file diff --git a/dockerfiles/postgresql/Dockerfile b/dockerfiles/postgresql/Dockerfile new file mode 100644 index 0000000..086173f --- /dev/null +++ b/dockerfiles/postgresql/Dockerfile @@ -0,0 +1,7 @@ +FROM postgres:9.6-alpine + +# ENV POSTGRES_USER=postgres +# ENV POSTGRES_PASSWORD=postgres + +# run create.sql on init +# ADD create.sql /docker-entrypoint-initdb.d \ No newline at end of file diff --git a/dockerfiles/py/.app_env b/dockerfiles/py/.app_env new file mode 100644 index 0000000..002bc18 --- /dev/null +++ b/dockerfiles/py/.app_env @@ -0,0 +1,7 @@ +PORT=5000 +HOST=0.0.0.0 +BASE_URL=http://0.0.0.0:8000 +HEALTH_CHECK_URL=http://0.0.0.0:8000/health_check +POSTGRES_URL=postgres://user:password@postgres:5432/db +REDIS_SERVER=redis://redis:6385/0 +KAFKA_SERVER=kafka://kafka:9092 \ No newline at end of file diff --git a/dockerfiles/py/Dockerfile b/dockerfiles/py/Dockerfile new file mode 100644 index 0000000..41896fb --- /dev/null +++ b/dockerfiles/py/Dockerfile @@ -0,0 +1,42 @@ +FROM python:3.7.6-slim + +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +ENV PIP_FORMAT=legacy + +RUN apt-get -y update && apt-get install -y python-pip python-dev libzbar-dev bash \ + gcc python3-dev git libc-dev + +RUN echo 'deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main' >> /etc/apt/sources.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends apt-utils + +RUN apt-get install -y netcat && apt-get autoremove -y + +RUN adduser --disabled-password --gecos '' myuser + +# RUN groupadd -r xuzer && useradd -r -g xuzer xuzer + +RUN pip install --upgrade pip + +COPY requirements.txt /requirements.txt +RUN pip install --no-cache-dir -r /requirements.txt + +RUN mkdir -p /main + +WORKDIR /main + +# Faust +COPY ./dockerfiles/py/faustRun.sh /faustRun.sh +RUN chmod +x /faustRun.sh + +# App +COPY ./dockerfiles/py/appRun.sh /appRun.sh +RUN chmod +x /appRun.sh + +# App Builder +COPY ./dockerfiles/py/builder.sh /builder.sh +RUN chmod +x /builder.sh + +CMD ["/builder.sh"] diff --git a/dockerfiles/py/appRun.sh b/dockerfiles/py/appRun.sh new file mode 100644 index 0000000..5d12b46 --- /dev/null +++ b/dockerfiles/py/appRun.sh @@ -0,0 +1,31 @@ +#!/bin/bash +#!/bin/sh + + +set -o errexit +set -o nounset + + + +n=10 + +while [ $n -gt 0 ] +do + echo "Wait for postgres $n more times." + n=$(( n-1 )) + sleep 5 +done + + +while python check_create_db.py; do echo 'connecting to database...'; sleep 2; done; + +echo ". . . . . Database Connection Is Done! . . . . ." + + +echo ". . . . . Web Boot Up In Progress! . . . . ." + +uvicorn bootUp:app --host ${HOST} --port ${PORT} --reload --ws 'auto' --loop 'auto' --workers 8 + +# python bootUp.py + +exec "$@" \ No newline at end of file diff --git a/dockerfiles/py/builder.sh b/dockerfiles/py/builder.sh new file mode 100644 index 0000000..83cfe58 --- /dev/null +++ b/dockerfiles/py/builder.sh @@ -0,0 +1,10 @@ +#!/bin/bash +#!/bin/sh + +set -o errexit +set -o pipefail +set -o nounset + +echo "No task assigned!" + +exec "$@" \ No newline at end of file diff --git a/dockerfiles/py/faustRun.sh b/dockerfiles/py/faustRun.sh new file mode 100644 index 0000000..b0d8d14 --- /dev/null +++ b/dockerfiles/py/faustRun.sh @@ -0,0 +1,30 @@ +#!/bin/bash +#!/bin/sh + +set -o errexit +set -o nounset + + + +n=8 + +while [ $n -gt 0 ] +do + echo "Wait for kafka and redis $n more times." + n=$(( n-1 )) + sleep 2 +done + +pytest tests/test_health_check.py -s + +echo ". . . . . Health Check Is Done! . . . . ." +sleep 5 + +while python check_faust.py; do echo 'faust is running...'; sleep 2; done; + +echo ". . . . . Faust Is Done! . . . . ." + + +faust -A app.tools.faust_:faust_app worker -l info -p 6066 + +exec "$@" \ No newline at end of file diff --git a/main/app/__init__.py b/main/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/app/api/__init__.py b/main/app/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/app/api/config.py b/main/app/api/config.py new file mode 100644 index 0000000..2d96622 --- /dev/null +++ b/main/app/api/config.py @@ -0,0 +1,42 @@ +from starlette.responses import PlainTextResponse, JSONResponse, Response +from starlette.routing import Route +from pydantic import BaseModel +import asyncio +import json +from app.db.handler import pgQuery + +pg = pgQuery() + +class number_serializer(BaseModel): + number: float + +async def homepage(request): + + dict_Values = await pg.getAll(database='qa') + # print(dict_Values) + return Response(json.dumps(dict_Values), status_code=200, media_type="application/json") + +async def health_check(request): + return PlainTextResponse('up', status_code=200) + + +async def getSquare(request): + n = request.path_params['number'] + n_ser = number_serializer(**{"number": n}) + + saved = await pg.saveData(database='qa', question=n_ser.number, answer=n_ser.number**2) + print(saved) + return JSONResponse({'result': n_ser.number**2}, status_code=200) + + + +async def startup(): + print('Ready to go fast!') + + +routes = [ + Route('/', homepage), + Route('/health_check', health_check, name="health_check"), + Route("/square/{number}", getSquare), + +] \ No newline at end of file diff --git a/main/app/db/__init__.py b/main/app/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/app/db/connection.py b/main/app/db/connection.py new file mode 100644 index 0000000..c46bcce --- /dev/null +++ b/main/app/db/connection.py @@ -0,0 +1,69 @@ +from os import getenv +import asyncpg +from datetime import datetime + + +class Postgres: + + def __init__(self): + self.db_url = getenv('POSTGRES_URL') + + async def checkConnection(self): + conn = await asyncpg.connect(self.db_url) + await conn.execute(''' + CREATE TABLE IF NOT EXISTS testusers( + id serial PRIMARY KEY, + name text, + dob date + ) + ''') + + # Insert a record into the created table. + await conn.execute(''' + INSERT INTO testusers(name, dob) VALUES($1, $2) + ''', 'Bob', datetime.utcnow()) + + # Select a row from the table. + row = await conn.fetchrow( + 'SELECT * FROM testusers WHERE name = $1', 'Bob') + + print(dict(row), type(row)) + + # test ideas:1 + print('------test idea1---------') + record=('Ali',datetime.utcnow()) + await conn.execute(''' + INSERT INTO testusers(name, dob) VALUES($1, $2) + ''', record[0], record[1]) + allrow = await conn.fetch('SELECT name FROM testusers') + print(allrow, type(allrow)) + + print([dict(row) for row in allrow]) + print('# test ideas:1 :::::SAVED to USD_BTC table!!') + + # test ideas:2 + print('------test idea2---------') + db = 'testusers' + trow = await conn.fetch('SELECT name FROM {}'.format(db)) + print(trow[-1]) + print('# test ideas:2 :::::Got it!!') + + + # test ideas:3 + print('------test idea3---------') + record=('Alireza',datetime.utcnow()) + que = '''INSERT INTO {}(name, dob) VALUES($1, $2)'''.format('testusers') + await conn.execute(que, record[0], record[1]) + + allrow = await conn.fetch('SELECT name FROM {}'.format('testusers')) + print(allrow, type(allrow)) + print([dict(row) for row in allrow]) + print('# test ideas:3 :::::Worked!!') + + + # Drop Table + query = "DROP TABLE IF EXISTS {} CASCADE;".format("testusers") + await conn.execute(query) + + print('\n\n', 'connection was succesfull!','\n\n', datetime.utcnow(), '\n\n\n' ) + await conn.close() \ No newline at end of file diff --git a/main/app/db/handler.py b/main/app/db/handler.py new file mode 100644 index 0000000..44ded66 --- /dev/null +++ b/main/app/db/handler.py @@ -0,0 +1,27 @@ +from os import getenv +import asyncpg +from datetime import datetime + + +class pgQuery: + def __init__(self): + self.db_url = getenv('POSTGRES_URL') + + async def saveData(self, database, question, answer): #database='qa' + + conn = await asyncpg.connect(self.db_url) + query = '''INSERT INTO {}(question, answer, created_at) + VALUES($1, $2, $3)'''.format(database) + await conn.execute(query, question, answer, datetime.now().isoformat()) + await conn.close() + return 'SAVED to ASyncPg!' + + + async def getAll(self, database): #database='qa' + + conn = await asyncpg.connect(self.db_url) + rows = await conn.fetch('SELECT * FROM {}'.format(database)) + await conn.close() + return [dict(row) for row in rows] + # return rows + \ No newline at end of file diff --git a/main/app/db/models.py b/main/app/db/models.py new file mode 100644 index 0000000..8e8dfe5 --- /dev/null +++ b/main/app/db/models.py @@ -0,0 +1,16 @@ +from tortoise import fields +from tortoise.models import Model + + +class qa(Model): + id = fields.IntField(pk=True) + question = fields.FloatField(source_field='question') + answer = fields.FloatField(source_field='answer') + created_at = fields.TextField(source_field='created_at') + + class Meta: + table = "qa" + table_description = "This table contains question and answer value" + + def __str__(self): + return "question is square of {} and answer is {}.".format(self.question, self.answer) \ No newline at end of file diff --git a/main/app/db/tor_db_handler.py b/main/app/db/tor_db_handler.py new file mode 100644 index 0000000..033a576 --- /dev/null +++ b/main/app/db/tor_db_handler.py @@ -0,0 +1,17 @@ +from os import getenv +from tortoise import Tortoise +from app.db.models import qa + +class TorPostgre: + + def __init__(self): + self.db_url = getenv('POSTGRES_URL') + + async def initdb(self): + await Tortoise.init(db_url=self.db_url, modules={"models": ["app.db.models"]}) + await Tortoise.generate_schemas() + + async def checkall(self): + await self.initdb() + print("all q and a: ") + print(await qa.all()) \ No newline at end of file diff --git a/main/app/tools/__init__.py b/main/app/tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/app/tools/faust_.py b/main/app/tools/faust_.py new file mode 100644 index 0000000..ee272ec --- /dev/null +++ b/main/app/tools/faust_.py @@ -0,0 +1,41 @@ +from os import getenv +from faust import App +import logging +from app.db.handler import pgQuery +from datetime import datetime + +pg = pgQuery() + +redis_server = getenv('REDIS_SERVER','redis://redis:6385/0') +kafka_broker = getenv('KAFKA_SERVER', 'kafka://kafka:9092') + +faust_app = App( + 'main_app', + version=1, + autodiscover=True, + origin='app', + broker=kafka_broker, + store=redis_server, + key_serializer='json', + value_serializer='json', + ) + +@faust_app.task +async def on_started(): + print('Fasut Main APP STARTED . . . \n\n') + + +logging.basicConfig(filename='faustLogs.log', + level=logging.DEBUG, + format="[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s") + + +@faust_app.timer(interval=10) +async def fetch_Q_A(): + """ + every 3 sec return length of data that + has been stored in qa database + """ + dict_Values = await pg.getAll(database='qa') + setOfData = {datadct['question'] for datadct in dict_Values} + print(f'Length of Unique Data at {datetime.now()} is: {len(setOfData)}') diff --git a/main/bootUp.py b/main/bootUp.py new file mode 100644 index 0000000..a85a9d8 --- /dev/null +++ b/main/bootUp.py @@ -0,0 +1,12 @@ +import uvicorn +from os import getenv +from app.api.config import routes, startup +from starlette.applications import Starlette + +app = Starlette(debug=True, routes=routes, on_startup=[startup]) + + +if __name__ == '__main__': + H = getenv('HOST','0.0.0.0') + P = getenv('PORT',5000) + uvicorn.run(app, host=H, port=int(P)) \ No newline at end of file diff --git a/main/check_create_db.py b/main/check_create_db.py new file mode 100644 index 0000000..ce65545 --- /dev/null +++ b/main/check_create_db.py @@ -0,0 +1,32 @@ +import logging +import asyncio +from app.db.connection import Postgres +from app.db.tor_db_handler import TorPostgre + + +logging.basicConfig(filename='dblogfiles.log', + level=logging.DEBUG, + format="[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s") + +async def main(): + + conn = Postgres() + await conn.checkConnection() + + tor_db = TorPostgre() + await tor_db.checkall() + + + + +if __name__ == "__main__": + + try: + asyncio.get_event_loop().run_until_complete(main()) + + exit(1) + + except Exception as e: + + logging.error('Error! {}'.format(e)) + exit(0) diff --git a/main/check_faust.py b/main/check_faust.py new file mode 100644 index 0000000..8c9680c --- /dev/null +++ b/main/check_faust.py @@ -0,0 +1,29 @@ +from os import getenv +import faust +import logging +import asyncio +from app.tools.faust_ import faust_app as app + +logging.basicConfig(filename='faustLogs.log', + level=logging.DEBUG, + format="[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s") + +async def main(): + + await app.start() + logging.info('Faust Works') + await app.stop() + exit(1) + + + +if __name__ == '__main__': + + try: + asyncio.get_event_loop().run_until_complete(main()) + + except Exception as e: + + logging.error('Error! {}'.format(e)) + exit(0) + diff --git a/main/tests/__init__.py b/main/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/tests/test_health_check.py b/main/tests/test_health_check.py new file mode 100644 index 0000000..ba01763 --- /dev/null +++ b/main/tests/test_health_check.py @@ -0,0 +1,21 @@ +import logging +import pytest +from os import getenv +from bootUp import app +from starlette.testclient import TestClient + +logging.basicConfig(filename='testslogs.log', + level=logging.DEBUG, + format="[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s") + +health_check_url= getenv('HEALTH_CHECK_URL') + +@pytest.fixture(scope="module", name="client") +def fixture_client(): + with TestClient(app) as test_client: + yield test_client + +def test_database(client): + response = client.get("/health_check") + assert response.status_code == 200 + print('Health Checked!') \ No newline at end of file diff --git a/main/tests/test_locust.py b/main/tests/test_locust.py new file mode 100644 index 0000000..9eb99e2 --- /dev/null +++ b/main/tests/test_locust.py @@ -0,0 +1,27 @@ +from locust import HttpUser, TaskSet, task, between + +class UserBehavior(TaskSet): + @task(5) + def homepage(self): + self.client.get("/") + + @task(4) + def getSquare1(self): + self.client.get("/square/44") + + @task(4) + def getSquare2(self): + self.client.get("/square/33") + + @task(4) + def getSquare3(self): + self.client.get("/square/22") + + @task(4) + def getSquare4(self): + self.client.get("/square/11") + +class User(HttpUser): + tasks = [UserBehavior,] + host = "http://localhost:8000" + wait_time = between(5, 10) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d973b95 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,21 @@ +# Async Web App +starlette +uvicorn +asyncio +asgiref +syncer +httpx + +# Data +asyncpg==0.20.1 +pydantic==1.5.1 +tortoise-orm + +# Queueing +faust +faust[uvloop,fast,rocksdb,redis] + +# Automated Tests +pytest +locust +locust-swarm \ No newline at end of file