Skip to content

Commit aefd04e

Browse files
committed
fea(re)
1 parent 18064ba commit aefd04e

File tree

5 files changed

+207
-3
lines changed

5 files changed

+207
-3
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from mapswipe_workers import auth
2+
from mapswipe_workers.definitions import logger
3+
from mapswipe_workers.utils import gzip_str
4+
5+
6+
class Firebase:
7+
def __init__(self):
8+
self.fb_db = auth.firebaseDB()
9+
self.ref = self.fb_db.reference("")
10+
11+
def save_project_to_firebase(self, project):
12+
# if a geometry exists in projects we want to delete it since it is not used in clients.
13+
project.pop("geometry", None)
14+
# save project
15+
self.ref.update({f"v2/projects/{project['projectId']}": project})
16+
logger.info(
17+
f"{project['projectId']} -" f" uploaded project to firebase realtime database"
18+
)
19+
20+
21+
def save_groups_to_firebase(self, projectId, groups):
22+
23+
# save groups
24+
self.ref.update({f"v2/groups/{projectId}": groups})
25+
logger.info(
26+
f"{projectId} -" f" uploaded groups to firebase realtime database"
27+
)
28+
29+
def save_tasks_to_firebase(self, projectId, groupsOfTasks, useCompression: bool):
30+
task_upload_dict = {}
31+
for group_counter, group_id in enumerate(groupsOfTasks.keys()):
32+
for i in range(0, len(groupsOfTasks[group_id])):
33+
groupsOfTasks[group_id][i].pop("geometry", None)
34+
35+
tasks_list = groupsOfTasks[group_id]
36+
# for tasks of a building footprint project
37+
# we use compression to reduce storage size in firebase
38+
# since the tasks hold geometries their storage size
39+
# can get quite big otherwise
40+
if useCompression:
41+
# removing properties from each task and compress
42+
for task in tasks_list:
43+
task.pop("properties", None)
44+
45+
tasks_list = gzip_str.compress_tasks(tasks_list)
46+
47+
task_upload_dict[
48+
f"v2/tasks/{projectId}/{group_id}"
49+
] = tasks_list
50+
51+
# we upload tasks in batches of maximum 150 groups
52+
# this is to avoid the maximum write size limit in firebase
53+
if len(task_upload_dict) % 150 == 0 or (group_counter + 1) == len(
54+
groupsOfTasks
55+
):
56+
self.ref.update(task_upload_dict)
57+
logger.info(
58+
f"{projectId} -"
59+
f" uploaded 150 groups with tasks to firebase realtime database"
60+
)
61+
task_upload_dict = {}

mapswipe_workers/mapswipe_workers/project_types/base/project.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,15 @@ def save_project(self):
172172
raise CustomError(e)
173173

174174
try:
175-
self.save_to_firebase(
175+
self.save_project_to_firebase(project)
176+
self.save_groups_to_firebase(project["projectId"], groups)
177+
self.save_tasks_to_firebase(project["projectId"], groupsOfTasks)
178+
179+
"""self.save_to_firebase(
176180
project,
177181
groups,
178182
groupsOfTasks,
179-
)
183+
)"""
180184
logger.info(
181185
f"{self.projectId}" f" - the project has been saved" f" to firebase"
182186
)
@@ -197,6 +201,18 @@ def save_project(self):
197201

198202
return True
199203

204+
@abstractmethod
205+
def save_project_to_firebase(self, project):
206+
pass
207+
208+
@abstractmethod
209+
def save_groups_to_firebase(self, projectId: str, groups: list):
210+
pass
211+
212+
@abstractmethod
213+
def save_tasks_to_firebase(self, projectId: str, tasks: list):
214+
pass
215+
200216
def save_to_firebase(self, project, groups, groupsOfTasks):
201217

202218
# remove wkt geometry attribute of projects and tasks

mapswipe_workers/mapswipe_workers/project_types/tile_classification/project.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from mapswipe_workers.firebase.firebase import Firebase
12
from mapswipe_workers.project_types.base.project import BaseProject
23

34
from mapswipe_workers.project_types.base.tile_server import BaseTileServer
@@ -6,7 +7,6 @@
67

78

89
class TileClassification(BaseProject):
9-
#TileServer tileServer
1010
def __init__(self, project_draft: dict):
1111
super().__init__(project_draft)
1212
# Note: this will be overwritten by validate_geometry in mapswipe_workers.py
@@ -17,3 +17,14 @@ def __init__(self, project_draft: dict):
1717
def validate_geometries(self):
1818
wkt_geometry, self.validInputGeometries = validate_geometries(self.projectId, self.geometry, self.zoomLevel)
1919
return wkt_geometry
20+
21+
def save_project_to_firebase(self, project):
22+
firebase = Firebase()
23+
firebase.save_project_to_firebase(project)
24+
25+
def save_groups_to_firebase(self, projectId: str, groups: list):
26+
firebase = Firebase()
27+
firebase.save_groups_to_firebase(projectId, groups)
28+
29+
def save_tasks_to_firebase(self, projectId: str, tasks: list):
30+
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"geometry": {"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[34.975833892822266,-15.899098066386088],[35.089302062988274,-15.899098066386088],[35.089302062988274,-15.820002241903946],[34.975833892822266,-15.820002241903946],[34.975833892822266,-15.899098066386088]]]},"properties":{}}]},
3+
"archived" : false,
4+
"created" : "2020-02-03T14:31:08.192136Z",
5+
"createdBy" : "test manager",
6+
"groupMaxSize" : 0,
7+
"groupSize" : 120,
8+
"image" : "",
9+
"isFeatured" : false,
10+
"lookFor" : "buildings",
11+
"name" : "test - Malawi \ntest",
12+
"progress" : 0,
13+
"projectDetails" : "test",
14+
"projectId" : "test_build_area",
15+
"projectNumber" : "1",
16+
"projectRegion" : "Malawi",
17+
"projectTopic" : "test",
18+
"projectType" : 1,
19+
"requestingOrganisation" : "test",
20+
"requiredResults" : 12537,
21+
"resultCount" : 0,
22+
"status" : "inactive",
23+
"tileServer" : {
24+
"apiKey" : "",
25+
"credits" : "© 2019 Microsoft Corporation, Earthstar Geographics SIO",
26+
"name" : "bing",
27+
"url" : "https://ecn.t0.tiles.virtualearth.net/tiles/a{quad_key}.jpeg?g=7505&mkt=en-US&token={key}"
28+
},
29+
"verificationNumber" : 3,
30+
"zoomLevel" : 18
31+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import unittest
2+
import os
3+
import json
4+
5+
from firebase_admin.exceptions import FirebaseError
6+
7+
from mapswipe_workers import auth
8+
from mapswipe_workers.firebase.firebase import Firebase
9+
from tests.integration import tear_down
10+
11+
12+
class TestFirebase(unittest.TestCase):
13+
def setUp(self):
14+
self.firebase = Firebase()
15+
self.ids = []
16+
17+
def tearDown(self):
18+
self.fb_db = None
19+
for id in self.ids:
20+
tear_down.delete_test_data(id)
21+
22+
def test_project_to_firebase(self):
23+
path = (
24+
"./fixtures/tile_map_service_grid/projects/build_area_with_geometry.json"
25+
)
26+
test_dir = os.path.dirname(os.path.abspath(__file__))
27+
with open(os.path.join(test_dir, path)) as json_file:
28+
project = json.load(json_file)
29+
self.ids.append(project["projectId"])
30+
self.firebase.save_project_to_firebase(project)
31+
32+
self.firebase.ref = self.firebase.fb_db.reference(f"/v2/projects/{project['projectId']}")
33+
result = self.firebase.ref.get(shallow=True)
34+
self.assertIsNotNone(result)
35+
self.assertNotIn("geometry", result)
36+
37+
def test_groups_to_firebase(self):
38+
path = (
39+
"./fixtures/tile_map_service_grid/groups/build_area.json"
40+
)
41+
test_dir = os.path.dirname(os.path.abspath(__file__))
42+
with open(os.path.join(test_dir, path)) as json_file:
43+
groups = json.load(json_file)
44+
project_id = groups["g101"]["projectId"]
45+
self.ids.append(project_id)
46+
self.firebase.save_groups_to_firebase(project_id, groups)
47+
48+
self.firebase.ref = self.firebase.fb_db.reference(f"/v2/groups/{project_id}")
49+
result = self.firebase.ref.get(shallow=True)
50+
self.assertIsNotNone(result)
51+
52+
def test_tasks_to_firebase_with_compression(self):
53+
path = (
54+
"./fixtures/tile_map_service_grid/tasks/build_area.json"
55+
)
56+
test_dir = os.path.dirname(os.path.abspath(__file__))
57+
with open(os.path.join(test_dir, path)) as json_file:
58+
tasks = json.load(json_file)
59+
project_id = tasks["g101"][0]["projectId"]
60+
self.ids.append(project_id)
61+
self.firebase.save_tasks_to_firebase(project_id, tasks, useCompression=True)
62+
self.firebase.ref = self.firebase.fb_db.reference(f"/v2/tasks/{project_id}")
63+
result = self.firebase.ref.get()
64+
self.assertIsNotNone(result)
65+
self.assertNotIsInstance(result["g101"], list)
66+
67+
68+
def test_tasks_to_firebase_without_compression(self):
69+
path = (
70+
"./fixtures/tile_map_service_grid/tasks/build_area.json"
71+
)
72+
test_dir = os.path.dirname(os.path.abspath(__file__))
73+
with open(os.path.join(test_dir, path)) as json_file:
74+
tasks = json.load(json_file)
75+
project_id = tasks["g101"][0]["projectId"]
76+
self.ids.append(project_id)
77+
self.firebase.save_tasks_to_firebase(project_id, tasks, useCompression=False)
78+
self.firebase.ref = self.firebase.fb_db.reference(f"/v2/tasks/{project_id}")
79+
result = self.firebase.ref.get()
80+
self.assertIsNotNone(result)
81+
self.assertIsInstance(result["g101"], list)
82+
83+
84+
if __name__ == "__main__":
85+
unittest.main()

0 commit comments

Comments
 (0)