Skip to content

Commit 60f924a

Browse files
authored
Merge pull request #3104 from Sefaria/post-modify-text-only-on-changed
feat(linker): optimize text modification by processing only changed segments
2 parents f0d4cc2 + bccc0c8 commit 60f924a

1 file changed

Lines changed: 27 additions & 8 deletions

File tree

sefaria/tracker.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,13 @@ def modify_text(user, oref, vtitle, lang, text, vsource=None, **kwargs):
3636
if vsource:
3737
chunk.versionSource = vsource # todo: log this change
3838
if chunk.save():
39-
kwargs['skip_links'] = kwargs.get('skip_links', False) or chunk.has_manually_wrapped_refs()
40-
post_modify_text(user, action, oref, lang, vtitle, old_text, chunk.text, str(chunk.full_version._id), **kwargs)
39+
skip_links = kwargs.pop('skip_links', False) or chunk.has_manually_wrapped_refs()
40+
count_after = kwargs.pop("count_after", 1)
41+
version_id = str(chunk.full_version._id)
42+
43+
_post_modify_changed_segments(user, action, oref, lang, vtitle, old_text, text, version_id, skip_links=skip_links, **kwargs)
44+
45+
count_and_index(oref, lang, vtitle, to_count=count_after)
4146

4247
return chunk
4348

@@ -79,13 +84,12 @@ def populate_change_map(old_text, en_tref, he_tref, _):
7984
error_map[oref.normal()] = f"Ref doesn't match schema of version. Exception: {repr(e)}"
8085
version.save()
8186

87+
skip_links = kwargs.pop('skip_links', False) or getattr(version, 'hasManuallyWrappedRefs', False)
8288
for old_text, new_text, oref in change_map.values():
8389
if oref.normal() in error_map: continue
84-
kwargs['skip_links'] = kwargs.get('skip_links', False) or getattr(version, 'hasManuallyWrappedRefs', False)
8590
# hard-code `count_after` to False here. It will be called later on the whole index once
8691
# (which is all that's necessary)
87-
kwargs['count_after'] = False
88-
post_modify_text(user, kwargs.get("type"), oref, version.language, version.versionTitle, old_text, new_text, str(version._id), **kwargs)
92+
post_modify_text(user, kwargs.get("type"), oref, version.language, version.versionTitle, old_text, new_text, str(version._id), skip_links=skip_links, count_after=False, **kwargs)
8993

9094
count_segments(version.get_index())
9195
return error_map
@@ -138,15 +142,15 @@ def modify_node(jagged_array_node):
138142
count_segments(version.get_index())
139143

140144

141-
def post_modify_text(user, action, oref, lang, vtitle, old_text, curr_text, version_id, **kwargs) -> None:
145+
def post_modify_text(user, action, oref, lang, vtitle, old_text, curr_text, version_id, skip_links=False, count_after=1, **kwargs) -> None:
142146
model.log_text(user, action, oref, lang, vtitle, old_text, curr_text, **kwargs)
143147
if USE_VARNISH:
144148
invalidate_ref(oref, lang=lang, version=vtitle, purge=True)
145149
if oref.next_section_ref():
146150
invalidate_ref(oref.next_section_ref(), lang=lang, version=vtitle, purge=True)
147151
if oref.prev_section_ref():
148152
invalidate_ref(oref.prev_section_ref(), lang=lang, version=vtitle, purge=True)
149-
if not kwargs.get("skip_links", None):
153+
if not skip_links:
150154
if CELERY_ENABLED:
151155
generator = MarkedUpTextChunkGenerator(user_id=user, **kwargs)
152156
generator.generate_from_ref_and_version_id(oref, version_id)
@@ -155,7 +159,22 @@ def post_modify_text(user, action, oref, lang, vtitle, old_text, curr_text, vers
155159
if autolinker:
156160
autolinker.refresh_links(**kwargs)
157161

158-
count_and_index(oref, lang, vtitle, to_count=kwargs.get("count_after", 1))
162+
count_and_index(oref, lang, vtitle, to_count=count_after)
163+
164+
165+
def _post_modify_changed_segments(user, action, oref, lang, vtitle, old_text, new_text, version_id, skip_links=False, **kwargs):
166+
"""Recursively walk old_text/new_text and call post_modify_text only for changed segments."""
167+
if isinstance(new_text, list):
168+
if not isinstance(old_text, list):
169+
old_text = []
170+
padded_old = old_text + [""] * max(0, len(new_text) - len(old_text))
171+
for i in range(len(new_text)):
172+
if padded_old[i] != new_text[i]:
173+
_post_modify_changed_segments(user, action, oref.subref(i + 1), lang, vtitle, padded_old[i], new_text[i], version_id, skip_links=skip_links, **kwargs)
174+
else:
175+
# Segment level — call post_modify_text if changed
176+
if old_text != new_text:
177+
post_modify_text(user, action, oref, lang, vtitle, old_text, new_text, version_id, skip_links=skip_links, count_after=False, **kwargs)
159178

160179

161180
def count_and_index(oref, lang, vtitle, to_count=1):

0 commit comments

Comments
 (0)