-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.py
187 lines (146 loc) · 6.82 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import os
import socket
import asyncio
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, Response
from fastapi.responses import JSONResponse, FileResponse
from strawberry.fastapi import GraphQLRouter
import logging
import logging.handlers
from src.GraphTypeDefinitions import schema
from src.DBDefinitions import startEngine, ComposeConnectionString
from src.DBFeeder import initDB
# region logging setup
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s.%(msecs)03d\t%(levelname)s:\t%(message)s',
datefmt='%Y-%m-%dT%I:%M:%S')
SYSLOGHOST = os.getenv("SYSLOGHOST", None)
if SYSLOGHOST is not None:
[address, strport, *_] = SYSLOGHOST.split(':')
assert len(_) == 0, f"SYSLOGHOST {SYSLOGHOST} has unexpected structure, try `localhost:514` or similar (514 is UDP port)"
port = int(strport)
my_logger = logging.getLogger()
my_logger.setLevel(logging.INFO)
handler = logging.handlers.SysLogHandler(address=(address, port), socktype=socket.SOCK_DGRAM)
#handler = logging.handlers.SocketHandler('10.10.11.11', 611)
my_logger.addHandler(handler)
# endregion
# region DB setup
## Definice GraphQL typu (pomoci strawberry https://strawberry.rocks/)
## Strawberry zvoleno kvuli moznosti mit federovane GraphQL API (https://strawberry.rocks/docs/guides/federation, https://www.apollographql.com/docs/federation/)
## Definice DB typu (pomoci SQLAlchemy https://www.sqlalchemy.org/)
## SQLAlchemy zvoleno kvuli moznost komunikovat s DB asynchronne
## https://docs.sqlalchemy.org/en/14/core/future.html?highlight=select#sqlalchemy.future.select
## Zabezpecuje prvotni inicializaci DB a definovani Nahodne struktury pro "Univerzity"
# from gql_workflow.DBFeeder import createSystemDataStructureRoleTypes, createSystemDataStructureGroupTypes
connectionString = ComposeConnectionString()
def singleCall(asyncFunc):
"""Dekorator, ktery dovoli, aby dekorovana funkce byla volana (vycislena) jen jednou. Navratova hodnota je zapamatovana a pri dalsich volanich vracena.
Dekorovana funkce je asynchronni.
"""
resultCache = {}
async def result():
if resultCache.get("result", None) is None:
resultCache["result"] = await asyncFunc()
return resultCache["result"]
return result
@singleCall
async def RunOnceAndReturnSessionMaker():
"""Provadi inicializaci asynchronniho db engine, inicializaci databaze a vraci asynchronni SessionMaker.
Protoze je dekorovana, volani teto funkce se provede jen jednou a vystup se zapamatuje a vraci se pri dalsich volanich.
"""
makeDrop = os.getenv("DEMO", None) == "True"
logging.info(f'starting engine for "{connectionString} makeDrop={makeDrop}"')
result = await startEngine(
connectionstring=connectionString, makeDrop=makeDrop, makeUp=True
)
###########################################################################################################################
#
# zde definujte do funkce asyncio.gather
# vlozte asynchronni funkce, ktere maji data uvest do prvotniho konzistentniho stavu
async def initDBAndReport():
logging.info(f"initializing system structures")
await initDB(result)
logging.info(f"all done")
print(f"all done")
# asyncio.create_task(coro=initDBAndReport())
await initDBAndReport()
#
#
###########################################################################################################################
return result
# endregion
# region FastAPI setup
async def get_context(request: Request):
asyncSessionMaker = await RunOnceAndReturnSessionMaker()
from src.Dataloaders import createLoadersContext
context = createLoadersContext(asyncSessionMaker)
result = {**context}
result["request"] = request
return result
@asynccontextmanager
async def lifespan(app: FastAPI):
initizalizedEngine = await RunOnceAndReturnSessionMaker()
yield
app = FastAPI(lifespan=lifespan)
graphql_app = GraphQLRouter(
schema,
context_getter=get_context
)
app.include_router(graphql_app, prefix="/gql")
@app.get("/voyager", response_class=FileResponse)
async def graphiql():
realpath = os.path.realpath("./voyager.html")
return realpath
import prometheus_client
@app.get("/metrics")
async def metrics():
return Response(
content=prometheus_client.generate_latest(),
media_type=prometheus_client.CONTENT_TYPE_LATEST
)
logging.info("All initialization is done")
# @app.get('/hello')
# def hello():
# return {'hello': 'world'}
###########################################################################################################################
#
# pokud jste pripraveni testovat GQL funkcionalitu, rozsirte apollo/server.js
#
###########################################################################################################################
# endregion
# region ENV setup tests
def envAssertDefined(name, default=None):
result = os.getenv(name, None)
assert result is not None, f"{name} environment variable must be explicitly defined"
return result
DEMO = envAssertDefined("DEMO", None)
GQLUG_ENDPOINT_URL = envAssertDefined("GQLUG_ENDPOINT_URL", None)
assert (DEMO in ["True", "true", "False", "false"]), "DEMO environment variable can have only `True` or `False` values"
DEMO = DEMO in ["True", "true"]
if DEMO:
print("####################################################")
print("# #")
print("# RUNNING IN DEMO #")
print("# #")
print("####################################################")
logging.info("####################################################")
logging.info("# #")
logging.info("# RUNNING IN DEMO #")
logging.info("# #")
logging.info("####################################################")
else:
print("####################################################")
print("# #")
print("# RUNNING DEPLOYMENT #")
print("# #")
print("####################################################")
logging.info("####################################################")
logging.info("# #")
logging.info("# RUNNING DEPLOYMENT #")
logging.info("# #")
logging.info("####################################################")
logging.info(f"DEMO = {DEMO}")
logging.info(f"SYSLOGHOST = {SYSLOGHOST}")
logging.info(f"GQLUG_ENDPOINT_URL = {GQLUG_ENDPOINT_URL}")