|
a/Allura/allura/model/index.py |
|
b/Allura/allura/model/index.py |
|
... |
|
... |
14 |
from ming.utils import LazyProperty
|
14 |
from ming.utils import LazyProperty
|
15 |
from ming.orm import MappedClass, session
|
15 |
from ming.orm import MappedClass, session
|
16 |
from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty
|
16 |
from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty
|
17 |
|
17 |
|
18 |
from allura.lib import helpers as h
|
18 |
from allura.lib import helpers as h
|
19 |
from allura.lib.search import find_shortlinks, solarize
|
|
|
20 |
|
19 |
|
21 |
from .session import main_orm_session
|
20 |
from .session import main_orm_session
|
22 |
|
21 |
|
23 |
log = logging.getLogger(__name__)
|
22 |
log = logging.getLogger(__name__)
|
24 |
|
23 |
|
|
... |
|
... |
82 |
_id = FieldProperty(S.ObjectId)
|
81 |
_id = FieldProperty(S.ObjectId)
|
83 |
ref_id = ForeignIdProperty(ArtifactReference)
|
82 |
ref_id = ForeignIdProperty(ArtifactReference)
|
84 |
project_id = ForeignIdProperty('Project')
|
83 |
project_id = ForeignIdProperty('Project')
|
85 |
app_config_id = ForeignIdProperty('AppConfig')
|
84 |
app_config_id = ForeignIdProperty('AppConfig')
|
86 |
link = FieldProperty(str)
|
85 |
link = FieldProperty(str)
|
|
|
86 |
url = FieldProperty(str)
|
87 |
|
87 |
|
88 |
# Relation Properties
|
88 |
# Relation Properties
|
89 |
project = RelationProperty('Project')
|
89 |
project = RelationProperty('Project')
|
90 |
app_config = RelationProperty('AppConfig')
|
90 |
app_config = RelationProperty('AppConfig')
|
91 |
ref = RelationProperty('ArtifactReference')
|
91 |
ref = RelationProperty('ArtifactReference')
|
|
... |
|
... |
117 |
if result is None:
|
117 |
if result is None:
|
118 |
try:
|
118 |
try:
|
119 |
result = cls(
|
119 |
result = cls(
|
120 |
ref_id = a.index_id(),
|
120 |
ref_id = a.index_id(),
|
121 |
project_id = a.app_config.project_id,
|
121 |
project_id = a.app_config.project_id,
|
122 |
app_config_id = a.app_config._id,
|
122 |
app_config_id = a.app_config._id)
|
123 |
link = a.shorthand_id())
|
|
|
124 |
session(result).flush(result)
|
123 |
session(result).flush(result)
|
125 |
except pymongo.errors.DuplicateKeyError: # pragma no cover
|
124 |
except pymongo.errors.DuplicateKeyError: # pragma no cover
|
126 |
session(result).expunge(result)
|
125 |
session(result).expunge(result)
|
127 |
result = cls.query.get(ref_id=a.index_id())
|
126 |
result = cls.query.get(ref_id=a.index_id())
|
|
|
127 |
result.link = a.shorthand_id()
|
|
|
128 |
result.url = a.url()
|
128 |
return result
|
129 |
return result
|
129 |
|
130 |
|
130 |
@classmethod
|
131 |
@classmethod
|
131 |
def from_links(cls, *links):
|
132 |
def from_links(cls, *links):
|
132 |
'''Convert a sequence of shortlinks to the matching Shortlink objects'''
|
133 |
'''Convert a sequence of shortlinks to the matching Shortlink objects'''
|
|
... |
|
... |
189 |
app=None,
|
190 |
app=None,
|
190 |
artifact=parts[0])
|
191 |
artifact=parts[0])
|
191 |
else:
|
192 |
else:
|
192 |
return None
|
193 |
return None
|
193 |
|
194 |
|
194 |
class IndexOp(MappedClass):
|
|
|
195 |
'''Queued operations for offline indexing.
|
|
|
196 |
'''
|
|
|
197 |
class __mongometa__:
|
|
|
198 |
session = main_orm_session
|
|
|
199 |
name = 'index_op'
|
|
|
200 |
indexes = [
|
|
|
201 |
[ ('worker', ming.ASCENDING),
|
|
|
202 |
('ref_id', ming.ASCENDING),
|
|
|
203 |
('timestamp', ming.DESCENDING),
|
|
|
204 |
],
|
|
|
205 |
]
|
|
|
206 |
|
|
|
207 |
_id = FieldProperty(S.ObjectId)
|
|
|
208 |
op = FieldProperty(S.OneOf('add', 'del'))
|
|
|
209 |
worker = FieldProperty(str, if_missing=None)
|
|
|
210 |
ref_id = ForeignIdProperty('ArtifactReference')
|
|
|
211 |
timestamp = FieldProperty(datetime, if_missing=datetime.utcnow)
|
|
|
212 |
|
|
|
213 |
ref = RelationProperty('ArtifactReference')
|
|
|
214 |
|
|
|
215 |
def __repr__(self):
|
|
|
216 |
return '<%s %s (%s) @%s>' % (
|
|
|
217 |
self.op, self.ref_id, self.worker, self.timestamp.isoformat())
|
|
|
218 |
|
|
|
219 |
@classmethod
|
|
|
220 |
def add_op(cls, artifact):
|
|
|
221 |
return cls(op='add', ref_id=artifact.index_id())
|
|
|
222 |
|
|
|
223 |
@classmethod
|
|
|
224 |
def del_op(cls, artifact):
|
|
|
225 |
return cls(op='del', ref_id=artifact.index_id())
|
|
|
226 |
|
|
|
227 |
@classmethod
|
|
|
228 |
def lock_ops(cls, worker):
|
|
|
229 |
'''Lock all the outstanding indexops to the given worker'''
|
|
|
230 |
cls.query.update(
|
|
|
231 |
dict(worker=None),
|
|
|
232 |
{'$set': dict(worker=worker)},
|
|
|
233 |
multi=True)
|
|
|
234 |
|
|
|
235 |
@classmethod
|
|
|
236 |
def remove_ops(cls, worker):
|
|
|
237 |
'''Remove all the ops locked by the given worker'''
|
|
|
238 |
cls.query.remove(dict(worker=worker))
|
|
|
239 |
|
|
|
240 |
@classmethod
|
|
|
241 |
def unlock_ops(cls, worker):
|
|
|
242 |
'''Unlock all the outstanding indexops to the given worker
|
|
|
243 |
|
|
|
244 |
Generally only used if the worker dies.
|
|
|
245 |
'''
|
|
|
246 |
cls.query.update(
|
|
|
247 |
dict(worker=worker),
|
|
|
248 |
{'$set': dict(worker=None)},
|
|
|
249 |
multi=True)
|
|
|
250 |
|
|
|
251 |
@classmethod
|
|
|
252 |
def find_ops(cls, worker):
|
|
|
253 |
'''Return the most relevant ops locked by worker
|
|
|
254 |
|
|
|
255 |
This method will only return the most recent op for a particular
|
|
|
256 |
artifact (which is what you actually want).
|
|
|
257 |
'''
|
|
|
258 |
q = (cls
|
|
|
259 |
.query
|
|
|
260 |
.find(dict(worker=worker))
|
|
|
261 |
.sort('ref_id')
|
|
|
262 |
.sort('timestamp', ming.DESCENDING))
|
|
|
263 |
for ref_id, ops in groupby(q, key=lambda o: o.ref_id):
|
|
|
264 |
yield ops.next()
|
|
|
265 |
|
|
|
266 |
def __call__(self):
|
|
|
267 |
from allura.model.artifact import Snapshot
|
|
|
268 |
try:
|
|
|
269 |
if self.op == 'add':
|
|
|
270 |
artifact = self.ref.artifact
|
|
|
271 |
Shortlink.from_artifact(artifact)
|
|
|
272 |
s = solarize(artifact)
|
|
|
273 |
if s is not None:
|
|
|
274 |
g.solr.add([s])
|
|
|
275 |
if not isinstance(artifact, Snapshot):
|
|
|
276 |
self.ref.references = [
|
|
|
277 |
link.ref_id for link in find_shortlinks(s['text']) ]
|
|
|
278 |
else:
|
|
|
279 |
g.solr.delete(id=self.ref_id)
|
|
|
280 |
ArtifactReference.query.remove(dict(_id=self.ref_id))
|
|
|
281 |
Shortlink.query.remove(dict(ref_id=self.ref_id))
|
|
|
282 |
except:
|
|
|
283 |
log.exception('Error with %r', self)
|
|
|
284 |
self.worker = 'ERROR'
|
|
|
285 |
session(self).flush(self)
|
|
|