diff --git a/models.py b/models.py index 0b23d9f..796f1d8 100644 --- a/models.py +++ b/models.py @@ -844,6 +844,13 @@ class Object(StringIdModel): if self.as1: actor = (as1.get_object(self.as1, 'actor') or as1.get_object(self.as1, 'author')) + # hydrate from datastore if available + # TODO: optimize! this is called serially in loops, eg in home.html + if set(actor.keys()) == {'id'} and self.source_protocol: + proto = PROTOCOLS[self.source_protocol] + actor_obj = proto.load(actor['id'], remote=False) + if actor_obj and actor_obj.as1: + actor = actor_obj.as1 if not actor: return '' diff --git a/pages.py b/pages.py index 2acaf1b..3fae339 100644 --- a/pages.py +++ b/pages.py @@ -121,6 +121,9 @@ def home(protocol, id): load_user(protocol, id) query = Object.query(Object.feed == g.user.key) objects, before, after = fetch_objects(query, by=Object.created) + + # this calls Object.actor_link serially for each object, which loads the + # actor from the datastore if necessary. TODO: parallelize those fetches return render_template('home.html', **TEMPLATE_VARS, **locals()) @@ -284,6 +287,7 @@ def fetch_objects(query, by=None): """ assert by is Object.updated or by is Object.created objects, new_before, new_after = fetch_page(query, Object, by=by) + objects = [o for o in objects if not o.deleted] # synthesize human-friendly content for objects for i, obj in enumerate(objects): diff --git a/tests/test_models.py b/tests/test_models.py index 97bf8a7..335ed5a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -417,6 +417,11 @@ class ObjectTest(TestCase): self.assertIn('href="fake:user">', got) self.assertIn('Alice', got) + def test_actor_link_object_in_datastore(self): + Object(id='fake:alice', as2={"name": "Alice"}).put() + obj = Object(id='x', source_protocol='fake', our_as1={'actor': 'fake:alice'}) + self.assertIn('Alice', obj.actor_link()) + def test_put_updates_load_cache(self): obj = Object(id='x', as2={}) obj.put()