media_repository.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014-2016 OpenMarket Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from ._base import SQLBaseStore
  16. class MediaRepositoryStore(SQLBaseStore):
  17. """Persistence for attachments and avatars"""
  18. def get_default_thumbnails(self, top_level_type, sub_type):
  19. return []
  20. def get_local_media(self, media_id):
  21. """Get the metadata for a local piece of media
  22. Returns:
  23. None if the media_id doesn't exist.
  24. """
  25. return self._simple_select_one(
  26. "local_media_repository",
  27. {"media_id": media_id},
  28. ("media_type", "media_length", "upload_name", "created_ts"),
  29. allow_none=True,
  30. desc="get_local_media",
  31. )
  32. def store_local_media(self, media_id, media_type, time_now_ms, upload_name,
  33. media_length, user_id):
  34. return self._simple_insert(
  35. "local_media_repository",
  36. {
  37. "media_id": media_id,
  38. "media_type": media_type,
  39. "created_ts": time_now_ms,
  40. "upload_name": upload_name,
  41. "media_length": media_length,
  42. "user_id": user_id.to_string(),
  43. },
  44. desc="store_local_media",
  45. )
  46. def get_url_cache(self, url, ts):
  47. """Get the media_id and ts for a cached URL as of the given timestamp
  48. Returns:
  49. None if the URL isn't cached.
  50. """
  51. def get_url_cache_txn(txn):
  52. # get the most recently cached result (relative to the given ts)
  53. sql = (
  54. "SELECT response_code, etag, expires, og, media_id, download_ts"
  55. " FROM local_media_repository_url_cache"
  56. " WHERE url = ? AND download_ts <= ?"
  57. " ORDER BY download_ts DESC LIMIT 1"
  58. )
  59. txn.execute(sql, (url, ts))
  60. row = txn.fetchone()
  61. if not row:
  62. # ...or if we've requested a timestamp older than the oldest
  63. # copy in the cache, return the oldest copy (if any)
  64. sql = (
  65. "SELECT response_code, etag, expires, og, media_id, download_ts"
  66. " FROM local_media_repository_url_cache"
  67. " WHERE url = ? AND download_ts > ?"
  68. " ORDER BY download_ts ASC LIMIT 1"
  69. )
  70. txn.execute(sql, (url, ts))
  71. row = txn.fetchone()
  72. if not row:
  73. return None
  74. return dict(zip((
  75. 'response_code', 'etag', 'expires', 'og', 'media_id', 'download_ts'
  76. ), row))
  77. return self.runInteraction(
  78. "get_url_cache", get_url_cache_txn
  79. )
  80. def store_url_cache(self, url, response_code, etag, expires, og, media_id,
  81. download_ts):
  82. return self._simple_insert(
  83. "local_media_repository_url_cache",
  84. {
  85. "url": url,
  86. "response_code": response_code,
  87. "etag": etag,
  88. "expires": expires,
  89. "og": og,
  90. "media_id": media_id,
  91. "download_ts": download_ts,
  92. },
  93. desc="store_url_cache",
  94. )
  95. def get_local_media_thumbnails(self, media_id):
  96. return self._simple_select_list(
  97. "local_media_repository_thumbnails",
  98. {"media_id": media_id},
  99. (
  100. "thumbnail_width", "thumbnail_height", "thumbnail_method",
  101. "thumbnail_type", "thumbnail_length",
  102. ),
  103. desc="get_local_media_thumbnails",
  104. )
  105. def store_local_thumbnail(self, media_id, thumbnail_width,
  106. thumbnail_height, thumbnail_type,
  107. thumbnail_method, thumbnail_length):
  108. return self._simple_insert(
  109. "local_media_repository_thumbnails",
  110. {
  111. "media_id": media_id,
  112. "thumbnail_width": thumbnail_width,
  113. "thumbnail_height": thumbnail_height,
  114. "thumbnail_method": thumbnail_method,
  115. "thumbnail_type": thumbnail_type,
  116. "thumbnail_length": thumbnail_length,
  117. },
  118. desc="store_local_thumbnail",
  119. )
  120. def get_cached_remote_media(self, origin, media_id):
  121. return self._simple_select_one(
  122. "remote_media_cache",
  123. {"media_origin": origin, "media_id": media_id},
  124. (
  125. "media_type", "media_length", "upload_name", "created_ts",
  126. "filesystem_id",
  127. ),
  128. allow_none=True,
  129. desc="get_cached_remote_media",
  130. )
  131. def store_cached_remote_media(self, origin, media_id, media_type,
  132. media_length, time_now_ms, upload_name,
  133. filesystem_id):
  134. return self._simple_insert(
  135. "remote_media_cache",
  136. {
  137. "media_origin": origin,
  138. "media_id": media_id,
  139. "media_type": media_type,
  140. "media_length": media_length,
  141. "created_ts": time_now_ms,
  142. "upload_name": upload_name,
  143. "filesystem_id": filesystem_id,
  144. "last_access_ts": time_now_ms,
  145. },
  146. desc="store_cached_remote_media",
  147. )
  148. def update_cached_last_access_time(self, origin_id_tuples, time_ts):
  149. def update_cache_txn(txn):
  150. sql = (
  151. "UPDATE remote_media_cache SET last_access_ts = ?"
  152. " WHERE media_origin = ? AND media_id = ?"
  153. )
  154. txn.executemany(sql, (
  155. (time_ts, media_origin, media_id)
  156. for media_origin, media_id in origin_id_tuples
  157. ))
  158. return self.runInteraction("update_cached_last_access_time", update_cache_txn)
  159. def get_remote_media_thumbnails(self, origin, media_id):
  160. return self._simple_select_list(
  161. "remote_media_cache_thumbnails",
  162. {"media_origin": origin, "media_id": media_id},
  163. (
  164. "thumbnail_width", "thumbnail_height", "thumbnail_method",
  165. "thumbnail_type", "thumbnail_length", "filesystem_id",
  166. ),
  167. desc="get_remote_media_thumbnails",
  168. )
  169. def store_remote_media_thumbnail(self, origin, media_id, filesystem_id,
  170. thumbnail_width, thumbnail_height,
  171. thumbnail_type, thumbnail_method,
  172. thumbnail_length):
  173. return self._simple_insert(
  174. "remote_media_cache_thumbnails",
  175. {
  176. "media_origin": origin,
  177. "media_id": media_id,
  178. "thumbnail_width": thumbnail_width,
  179. "thumbnail_height": thumbnail_height,
  180. "thumbnail_method": thumbnail_method,
  181. "thumbnail_type": thumbnail_type,
  182. "thumbnail_length": thumbnail_length,
  183. "filesystem_id": filesystem_id,
  184. },
  185. desc="store_remote_media_thumbnail",
  186. )
  187. def get_remote_media_before(self, before_ts):
  188. sql = (
  189. "SELECT media_origin, media_id, filesystem_id"
  190. " FROM remote_media_cache"
  191. " WHERE last_access_ts < ?"
  192. )
  193. return self._execute(
  194. "get_remote_media_before", self.cursor_to_dict, sql, before_ts
  195. )
  196. def delete_remote_media(self, media_origin, media_id):
  197. def delete_remote_media_txn(txn):
  198. self._simple_delete_txn(
  199. txn,
  200. "remote_media_cache",
  201. keyvalues={
  202. "media_origin": media_origin, "media_id": media_id
  203. },
  204. )
  205. self._simple_delete_txn(
  206. txn,
  207. "remote_media_cache_thumbnails",
  208. keyvalues={
  209. "media_origin": media_origin, "media_id": media_id
  210. },
  211. )
  212. return self.runInteraction("delete_remote_media", delete_remote_media_txn)