ChandimaPrabath commited on
Commit
73e339f
·
1 Parent(s): c8a3913

download a film to best instance

Browse files
Files changed (3) hide show
  1. LoadBalancer.py +49 -10
  2. api.py +23 -0
  3. app.py +7 -16
LoadBalancer.py CHANGED
@@ -148,16 +148,6 @@ class LoadBalancer:
148
  print(f"Error getting system proxies: {e}")
149
  return {}
150
 
151
- @staticmethod
152
- def download_film(title):
153
- """
154
- Downloads a film to a specific instance
155
-
156
- Args:
157
- title (str): The title of the film.
158
- """
159
- pass
160
-
161
  @staticmethod
162
  def update_film_store_json(title, url):
163
  """
@@ -231,6 +221,55 @@ class LoadBalancer:
231
  "total": "50 GB"}
232
  logging.info(f"Updated instance {instance} with cache size {cache_size}")
233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  #################################################################
235
  def load_json(self, file_path):
236
  """Load JSON data from a file."""
 
148
  print(f"Error getting system proxies: {e}")
149
  return {}
150
 
 
 
 
 
 
 
 
 
 
 
151
  @staticmethod
152
  def update_film_store_json(title, url):
153
  """
 
221
  "total": "50 GB"}
222
  logging.info(f"Updated instance {instance} with cache size {cache_size}")
223
 
224
+
225
+ def download_film_to_best_instance(self, title):
226
+ """
227
+ Downloads a film to the first instance that has more free space on the self.instance_health list variable.
228
+ The instance_health looks like this:
229
+ {
230
+ "https://unicone-studio-instance1.hf.space": {
231
+ "total": "50 GB",
232
+ "used": "3.33 GB"
233
+ }
234
+ }
235
+ Args:
236
+ title (str): The title of the film.
237
+ """
238
+ best_instance = None
239
+ max_free_space = -1
240
+
241
+ # Calculate free space for each instance
242
+ for instance_url, space_info in self.instance_health.items():
243
+ total_space = self._convert_to_gb(space_info['total'])
244
+ used_space = self._convert_to_gb(space_info['used'])
245
+ free_space = total_space - used_space
246
+
247
+ if free_space > max_free_space:
248
+ max_free_space = free_space
249
+ best_instance = instance_url
250
+
251
+ if best_instance:
252
+ result = self.instances_api.download_film(best_instance, title)
253
+ film_id = result["film_id"]
254
+ status = result["status"]
255
+ progress_url = f'{best_instance}/api/progress/{film_id}'
256
+ response = {
257
+ "film_id":film_id,
258
+ "status":status,
259
+ "progress_url":progress_url
260
+ }
261
+
262
+ return response
263
+ else:
264
+ logging.error("No suitable instance found for downloading the film.")
265
+ return {"error": "No suitable instance found for downloading the film."}
266
+
267
+ def _convert_to_gb(self, space_str):
268
+ """
269
+ Converts a space string like '50 GB' or '3.33 GB' to a float representing the number of GB.
270
+ """
271
+ return float(space_str.split()[0])
272
+
273
  #################################################################
274
  def load_json(self, file_path):
275
  """Load JSON data from a file."""
api.py CHANGED
@@ -15,3 +15,26 @@ class InstancesAPI:
15
  except requests.exceptions.RequestException as e:
16
  logging.error(f"Error contacting instance {instance_url}: {e}")
17
  return reports
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  except requests.exceptions.RequestException as e:
16
  logging.error(f"Error contacting instance {instance_url}: {e}")
17
  return reports
18
+
19
+ def download_film(self, instance_url, title):
20
+ """
21
+ Download a film to an instance.
22
+
23
+ If the download started, it returns a JSON like this:
24
+ example:
25
+ {"film_id": "my_spy_2020",
26
+ "status": "Download started"}
27
+
28
+ If the film has already been downloaded, it will return the video file.
29
+ """
30
+ data = {}
31
+ try:
32
+ response = requests.get(f"{instance_url}/api/film/{title}")
33
+ response.raise_for_status()
34
+ data = response.json()
35
+
36
+ except requests.exceptions.RequestException as e:
37
+ logging.error(f"Error contacting instance {instance_url}: {e}")
38
+ data = {"error": str(e)}
39
+
40
+ return data
app.py CHANGED
@@ -37,27 +37,18 @@ def get_movie_api(title):
37
 
38
  # Check if the film is already cached
39
  if title in film_store_data:
40
- cache_path = film_store_data[title]
41
- if os.path.exists(cache_path):
42
- return send_from_directory(os.path.dirname(cache_path), os.path.basename(cache_path))
43
-
44
  movie_path = load_balancer.find_movie_path(title)
45
 
46
  if not movie_path:
47
  return jsonify({"error": "Movie not found"}), 404
48
 
49
- cache_path = os.path.join(CACHE_DIR, movie_path)
50
- file_url = f"https://huggingface.co/{REPO}/resolve/main/{movie_path}"
51
- proxies = load_balancer.get_system_proxies()
52
- film_id = load_balancer.get_film_id(title)
53
-
54
- # Start the download in a separate thread if not already downloading
55
- if film_id not in load_balancer.download_threads or not load_balancer.download_threads[film_id].is_alive():
56
- thread = Thread(target=load_balancer.download_film, args=(file_url, TOKEN, cache_path, proxies, film_id, title))
57
- load_balancer.download_threads[film_id] = thread
58
- thread.start()
59
-
60
- return jsonify({"status": "Download started", "film_id": film_id})
61
 
62
  @app.route('/api/tv/<title>/<season>/<episode>', methods=['GET'])
63
  def get_tv_show_api(title, season, episode):
 
37
 
38
  # Check if the film is already cached
39
  if title in film_store_data:
40
+ url = film_store_data[title]
41
+ return jsonify({"url":url})
42
+
 
43
  movie_path = load_balancer.find_movie_path(title)
44
 
45
  if not movie_path:
46
  return jsonify({"error": "Movie not found"}), 404
47
 
48
+ # Start the download in a instance
49
+ response = load_balancer.download_film_to_best_instance(title=title)
50
+ if response:
51
+ return jsonify(response)
 
 
 
 
 
 
 
 
52
 
53
  @app.route('/api/tv/<title>/<season>/<episode>', methods=['GET'])
54
  def get_tv_show_api(title, season, episode):