Skip to content

Commit bcb01de

Browse files
feat(ping route): updates LAST_PING_TIME
BREAKING CHANGE: functions moved to utils_functions.py
1 parent a98eb92 commit bcb01de

File tree

5 files changed

+163
-119
lines changed

5 files changed

+163
-119
lines changed

config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ProdConfig(Config):
2525

2626
class DevConfig(Config):
2727
SSL = None
28-
ORIGINS = "http://localhost:3000"
28+
ORIGINS = ["*"]
2929
MINUTES_BEFORE_TIMEOUT = "1000"
3030
SECONDS_BETWEEN_SHUTDOWNS = "60"
3131
DATA_FOLDER = "./data/"

src/opengeodeweb_back/geode_functions.py

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
# Standard library imports
22
import os
3-
import time
4-
import threading
5-
import uuid
6-
import zipfile
73

84
# Third party imports
95
import flask
106
import opengeode_geosciences as og_gs
117
import opengeode as og
12-
import pkg_resources
13-
from jsonschema import validate
14-
from jsonschema.exceptions import ValidationError
158

169
# Local application imports
1710
from .geode_objects import geode_objects_dict
@@ -200,75 +193,6 @@ def get_inspector_children(obj):
200193
return new_object
201194

202195

203-
def versions(list_packages: list):
204-
list_with_versions = []
205-
for package in list_packages:
206-
list_with_versions.append(
207-
{
208-
"package": package,
209-
"version": pkg_resources.get_distribution(package).version,
210-
}
211-
)
212-
return list_with_versions
213-
214-
215-
def create_lock_file(
216-
folder_absolute_path,
217-
):
218-
if not os.path.exists(folder_absolute_path):
219-
os.mkdir(folder_absolute_path)
220-
id = uuid.uuid4()
221-
file_absolute_path = f"{folder_absolute_path}/{str(id)}.txt"
222-
f = open(file_absolute_path, "a")
223-
f.close()
224-
flask.g.UUID = id
225-
226-
227-
def create_time_file(folder_absolute_path):
228-
if not os.path.exists(folder_absolute_path):
229-
os.mkdir(folder_absolute_path)
230-
file_path = f"{folder_absolute_path}/time.txt"
231-
if not os.path.isfile(file_path):
232-
f = open(file_path, "w")
233-
f.close()
234-
235-
f = open(folder_absolute_path + "/time.txt", "w")
236-
f.write(str(time.time()))
237-
f.close()
238-
239-
240-
def remove_lock_file(folder_absolute_path):
241-
id = flask.g.UUID
242-
os.remove(f"{folder_absolute_path}/{str(id)}.txt")
243-
244-
245-
def set_interval(func, sec):
246-
def func_wrapper():
247-
set_interval(func, sec)
248-
func()
249-
250-
t = threading.Timer(sec, func_wrapper)
251-
t.daemon = True
252-
t.start()
253-
return t
254-
255-
256-
def extension_from_filename(filename):
257-
return os.path.splitext(filename)[1][1:]
258-
259-
260-
def validate_request(request, schema):
261-
json_data = request.get_json(force=True, silent=True)
262-
263-
if json_data is None:
264-
json_data = {}
265-
266-
try:
267-
validate(instance=json_data, schema=schema)
268-
except ValidationError as e:
269-
flask.abort(400, f"Validation error: {e.message}")
270-
271-
272196
def geographic_coordinate_systems(geode_object: str):
273197
if is_3D(geode_object):
274198
return og_gs.GeographicCoordinateSystem3D.geographic_coordinate_systems()
@@ -329,41 +253,3 @@ def create_coordinate_system(
329253
create_crs(
330254
geode_object, data, name, input_coordiante_system, output_coordiante_system
331255
)
332-
333-
334-
def send_file(upload_folder, saved_files, new_file_name):
335-
if len(saved_files) == 1:
336-
mimetype = "application/octet-binary"
337-
else:
338-
mimetype = "application/zip"
339-
new_file_name = os.path.splitext(new_file_name)[0] + ".zip"
340-
with zipfile.ZipFile(os.path.join(upload_folder, new_file_name), "w") as zipObj:
341-
for saved_file_path in saved_files:
342-
zipObj.write(
343-
saved_file_path,
344-
os.path.basename(saved_file_path),
345-
)
346-
347-
response = flask.send_from_directory(
348-
directory=upload_folder,
349-
path=new_file_name,
350-
as_attachment=True,
351-
mimetype=mimetype,
352-
)
353-
response.headers["new-file-name"] = new_file_name
354-
response.headers["Access-Control-Expose-Headers"] = "new-file-name"
355-
356-
return response
357-
358-
359-
def handle_exception(e):
360-
response = e.get_response()
361-
response.data = flask.json.dumps(
362-
{
363-
"code": e.code,
364-
"name": e.name,
365-
"description": e.description,
366-
}
367-
)
368-
response.content_type = "application/json"
369-
return response

src/opengeodeweb_back/routes/blueprint_routes.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
# Standard library imports
22
import json
33
import os
4+
import time
45

56
# Third party imports
67
import flask
7-
import flask_cors
8-
from .. import geode_functions
8+
from .. import geode_functions, utils_functions
99
import werkzeug
1010
import uuid
1111

12-
1312
routes = flask.Blueprint("routes", __name__)
14-
flask_cors.CORS(routes)
1513

14+
@routes.before_request
15+
def before_request():
16+
if "ping" not in flask.request.path:
17+
utils_functions.increment_request_counter(flask.current_app)
18+
19+
@routes.teardown_request
20+
def teardown_request(exception):
21+
if "ping" not in flask.request.path:
22+
utils_functions.decrement_request_counter(flask.current_app)
23+
utils_functions.update_last_request_time(flask.current_app)
1624

1725
schemas = os.path.join(os.path.dirname(__file__), "schemas")
1826

@@ -260,3 +268,19 @@ def save_viewable_file():
260268
},
261269
200,
262270
)
271+
272+
273+
with open(
274+
os.path.join(schemas, "ping.json"),
275+
"r",
276+
) as file:
277+
ping_json = json.load(file)
278+
279+
@routes.route(
280+
ping_json["route"],
281+
methods=ping_json["methods"],
282+
)
283+
def ping():
284+
utils_functions.validate_request(flask.request, ping_json)
285+
flask.current_app.config.update(LAST_PING_TIME=time.time())
286+
return flask.make_response({"message": "Flask server is running"}, 200)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"route": "/ping",
3+
"methods": [
4+
"POST"
5+
],
6+
"type": "object",
7+
"properties": {},
8+
"required": [],
9+
"additionalProperties": false
10+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Standard library imports
2+
import os
3+
import threading
4+
import time
5+
import zipfile
6+
7+
# Third party imports
8+
import flask
9+
from jsonschema import validate
10+
from jsonschema.exceptions import ValidationError
11+
import pkg_resources
12+
13+
# Local application imports
14+
15+
def increment_request_counter(current_app):
16+
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER"))
17+
REQUEST_COUNTER += 1
18+
current_app.config.update(REQUEST_COUNTER=REQUEST_COUNTER)
19+
20+
def decrement_request_counter(current_app):
21+
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER"))
22+
REQUEST_COUNTER -= 1
23+
current_app.config.update(REQUEST_COUNTER=REQUEST_COUNTER)
24+
25+
def update_last_request_time(current_app):
26+
LAST_REQUEST_TIME = time.time()
27+
current_app.config.update(LAST_REQUEST_TIME=LAST_REQUEST_TIME)
28+
29+
30+
def kill_task(current_app):
31+
DESKTOP_APP = bool(current_app.config.get("DESKTOP_APP"))
32+
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER"))
33+
LAST_PING_TIME = float(current_app.config.get("LAST_PING_TIME"))
34+
LAST_REQUEST_TIME = float(current_app.config.get("LAST_REQUEST_TIME"))
35+
MINUTES_BEFORE_TIMEOUT = float(current_app.config.get("MINUTES_BEFORE_TIMEOUT"))
36+
current_time = time.time()
37+
minutes_since_last_request = (current_time - LAST_REQUEST_TIME) / 60
38+
minutes_since_last_ping = (current_time - LAST_PING_TIME) / 60
39+
40+
if (((minutes_since_last_request > MINUTES_BEFORE_TIMEOUT) and (DESKTOP_APP == False)) or
41+
(minutes_since_last_ping > MINUTES_BEFORE_TIMEOUT)
42+
) and (REQUEST_COUNTER == 0):
43+
print("Server timed out due to inactivity, shutting down...", flush=True)
44+
os._exit(0)
45+
46+
47+
48+
def versions(list_packages: list):
49+
list_with_versions = []
50+
for package in list_packages:
51+
list_with_versions.append(
52+
{
53+
"package": package,
54+
"version": pkg_resources.get_distribution(package).version,
55+
}
56+
)
57+
return list_with_versions
58+
59+
60+
61+
def validate_request(request, schema):
62+
json_data = request.get_json(force=True, silent=True)
63+
64+
if json_data is None:
65+
json_data = {}
66+
67+
try:
68+
validate(instance=json_data, schema=schema)
69+
except ValidationError as e:
70+
flask.abort(400, f"Validation error: {e.message}")
71+
72+
73+
74+
def set_interval(func, sec, args=None):
75+
def func_wrapper():
76+
set_interval(func, sec, args)
77+
func(args)
78+
79+
t = threading.Timer(sec, func_wrapper)
80+
t.daemon = True
81+
t.start()
82+
return t
83+
84+
85+
def extension_from_filename(filename):
86+
return os.path.splitext(filename)[1][1:]
87+
88+
89+
def send_file(upload_folder, saved_files, new_file_name):
90+
if len(saved_files) == 1:
91+
mimetype = "application/octet-binary"
92+
else:
93+
mimetype = "application/zip"
94+
new_file_name = os.path.splitext(new_file_name)[0] + ".zip"
95+
with zipfile.ZipFile(os.path.join(upload_folder, new_file_name), "w") as zipObj:
96+
for saved_file_path in saved_files:
97+
zipObj.write(
98+
saved_file_path,
99+
os.path.basename(saved_file_path),
100+
)
101+
102+
response = flask.send_from_directory(
103+
directory=upload_folder,
104+
path=new_file_name,
105+
as_attachment=True,
106+
mimetype=mimetype,
107+
)
108+
response.headers["new-file-name"] = new_file_name
109+
response.headers["Access-Control-Expose-Headers"] = "new-file-name"
110+
111+
return response
112+
113+
114+
def handle_exception(e):
115+
response = e.get_response()
116+
response.data = flask.json.dumps(
117+
{
118+
"code": e.code,
119+
"name": e.name,
120+
"description": e.description,
121+
}
122+
)
123+
response.content_type = "application/json"
124+
return response

0 commit comments

Comments
 (0)