[Migration] remove podcasts_by_id
[mygpo.git] / mygpo / db / couchdb / podcast.py
blob9a16fddb4b8a6d057540dca0143b283b3e70a789
1 from hashlib import sha1
2 from datetime import datetime
4 from restkit import RequestFailed
5 from couchdbkit import MultipleResultsFound
7 from django.core.cache import cache
9 from mygpo.core.models import Podcast, PodcastGroup, PodcastSubscriberData
10 from mygpo.core.signals import incomplete_obj
11 from mygpo.decorators import repeat_on_conflict
12 from mygpo.cache import cache_result
13 from mygpo.utils import get_timestamp
14 from mygpo.db.couchdb import get_main_database, get_userdata_database, \
15 lucene_query
16 from mygpo.db import QueryParameterMissing
17 from mygpo.db.couchdb import get_main_database, get_single_result
18 from mygpo.db.couchdb.utils import multi_request_view, is_couchdb_id
20 import logging
21 logger = logging.getLogger(__name__)
24 def podcasts_groups_by_id(ids):
25 """ gets podcast groups and top-level podcasts for the given ids """
27 if ids is None:
28 raise QueryParameterMissing('ids')
30 if not ids:
31 return
33 db = get_main_database()
34 res = db.view('podcasts/podcasts_groups',
35 keys = ids,
36 include_docs = True,
39 for r in res:
40 obj = _wrap_pg(r)
42 if not obj:
43 yield None
44 continue
46 if obj.needs_update:
47 incomplete_obj.send_robust(sender=obj)
49 yield obj
52 def _wrap_pg(doc):
54 doc = doc['doc']
56 if not doc:
57 return None
59 if doc['doc_type'] == 'Podcast':
60 return Podcast.wrap(doc)
62 elif doc['doc_type'] == 'PodcastGroup':
63 return PodcastGroup.wrap(doc)
65 else:
66 logger.error('received unknown doc_type "%s"', doc['doc_type'])
69 def podcasts_to_dict(ids, use_cache=False):
71 if ids is None:
72 raise QueryParameterMissing('ids')
74 if not ids:
75 return dict()
78 ids = list(set(ids))
79 objs = dict()
81 cache_objs = []
82 if use_cache:
83 res = cache.get_many(ids)
84 cache_objs.extend(res.values())
85 ids = [x for x in ids if x not in res.keys()]
87 from mygpo.podcasts.models import Podcast
88 db_objs = Podcast.objects.filter(id__in=ids)
90 for obj in (cache_objs + db_objs):
92 # get_multi returns dict {'key': _id, 'error': 'not found'}
93 # for non-existing objects
94 if isinstance(obj, dict) and 'error' in obj:
95 _id = obj['key']
96 objs[_id] = None
97 continue
99 for i in obj.get_ids():
100 objs[i] = obj
102 if use_cache:
103 cache.set_many(dict( (obj.get_id(), obj) for obj in db_objs))
105 return objs
108 def subscriberdata_for_podcast(podcast_id):
110 if not podcast_id:
111 raise QueryParameterMissing('podcast_id')
113 db = get_main_database()
114 data = get_single_result(db, 'podcasts/subscriber_data',
115 key = podcast_id,
116 include_docs = True,
117 schema = PodcastSubscriberData,
120 if not data:
121 data = PodcastSubscriberData()
122 data.podcast = podcast_id
124 return data
128 def _wrap_podcast_group(res):
129 if res['doc']['doc_type'] == 'Podcast':
130 return Podcast.wrap(res['doc'])
131 else:
132 pg = PodcastGroup.wrap(res['doc'])
133 id = res['key']
134 return pg.get_podcast_by_id(id)
137 def search_wrapper(result):
138 doc = result['doc']
139 if doc['doc_type'] == 'Podcast':
140 p = Podcast.wrap(doc)
141 elif doc['doc_type'] == 'PodcastGroup':
142 p = PodcastGroup.wrap(doc)
143 p._id = result['id']
144 return p
147 @cache_result(timeout=60*60)
148 def search(q, offset=0, num_results=20):
150 if not q:
151 return [], 0
153 db = get_main_database()
155 FIELDS = ['title', 'description']
156 q = lucene_query(FIELDS, q)
158 try:
159 res = db.search('podcasts/search',
160 wrapper = search_wrapper,
161 include_docs = True,
162 limit = num_results,
163 stale = 'update_after',
164 skip = offset,
165 q = q,
168 podcasts = list(res)
170 for podcast in podcasts:
171 if podcast.needs_update:
172 incomplete_obj.send_robust(sender=podcast)
174 return podcasts, res.total_rows
176 except RequestFailed:
177 return [], 0
180 def update_additional_data(podcast, twitter):
181 podcast.twitter = twitter
182 podcast.save()
184 # clear the whole cache until we have a better invalidation mechanism
185 cache.clear()
188 def update_related_podcasts(podcast, related):
189 if podcast.related_podcasts == related:
190 return
192 podcast.related_podcasts = related
193 podcast.save()
196 def delete_podcast(podcast):
197 podcast.delete()