Skip to content

Commit

Permalink
fix: use algoliasearch v4 syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
shortcuts committed Nov 21, 2024
1 parent 5907b3e commit 523958e
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 81 deletions.
25 changes: 2 additions & 23 deletions algoliasearch_django/decorators.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
try:
# ContextDecorator was introduced in Python 3.2
from contextlib import ContextDecorator
except ImportError:
ContextDecorator = None
from functools import WRAPPER_ASSIGNMENTS, wraps
from contextlib import ContextDecorator
from functools import WRAPPER_ASSIGNMENTS

from django.db.models.signals import post_save, pre_delete

Expand All @@ -19,23 +15,6 @@ def available_attrs(fn):
return WRAPPER_ASSIGNMENTS


if ContextDecorator is None:
# ContextDecorator was introduced in Python 3.2
# See https://docs.python.org/3/library/contextlib.html#contextlib.ContextDecorator
class ContextDecorator:
"""
A base class that enables a context manager to also be used as a decorator.
"""

def __call__(self, func):
@wraps(func, assigned=available_attrs(func))
def inner(*args, **kwargs):
with self:
return func(*args, **kwargs)

return inner


def register(model):
"""
Register the given model class and wrapped AlgoliaIndex class with the Algolia engine:
Expand Down
115 changes: 73 additions & 42 deletions algoliasearch_django/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import logging

from algoliasearch.http.exceptions import AlgoliaException
from algoliasearch.search.models.operation_index_params import OperationIndexParams
from algoliasearch.search.models.operation_type import OperationType
from algoliasearch.search.models.search_params_object import SearchParamsObject
from django.db.models.query_utils import DeferredAttribute

from .settings import DEBUG
Expand Down Expand Up @@ -71,7 +74,7 @@ class AlgoliaIndex(object):

def __init__(self, model, client, settings):
"""Initializes the index."""
self.__init_index(client, model, settings)
self.__init_index(model, settings)

self.model = model
self.__client = client
Expand Down Expand Up @@ -170,7 +173,7 @@ def __init__(self, model, client, settings):
)
)

def __init_index(self, client, model, settings):
def __init_index(self, model, settings):
if not self.index_name:
self.index_name = model.__name__

Expand All @@ -189,9 +192,6 @@ def __init_index(self, client, model, settings):

self.tmp_index_name = tmp_index_name

self.__index = client.init_index(self.index_name)
self.__tmp_index = client.init_index(self.tmp_index_name)

@staticmethod
def _validate_geolocation(geolocation):
"""
Expand Down Expand Up @@ -315,10 +315,14 @@ def save_record(self, instance, update_fields=None, **kwargs):
try:
if update_fields:
obj = self.get_raw_record(instance, update_fields=update_fields)
result = self.__index.partial_update_object(obj)
result = self.__client.partial_update_object(
self.index_name, obj.get("objectID"), obj
)
else:
obj = self.get_raw_record(instance)
result = self.__index.save_object(obj)
result = self.__client.save_object(
self.index_name, obj.get("objectID"), obj
)
logger.info("SAVE %s FROM %s", obj["objectID"], self.model)
return result
except AlgoliaException as e:
Expand All @@ -333,7 +337,7 @@ def delete_record(self, instance):
"""Deletes the record."""
objectID = self.objectID(instance)
try:
self.__index.delete_object(objectID)
self.__client.delete_object(self.index_name, objectID)
logger.info("DELETE %s FROM %s", objectID, self.model)
except AlgoliaException as e:
if DEBUG:
Expand Down Expand Up @@ -369,19 +373,21 @@ def update_records(self, qs, batch_size=1000, **kwargs):
batch.append(dict(tmp))

if len(batch) >= batch_size:
self.__index.partial_update_objects(batch)
self.__client.partial_update_objects(self.index_name, batch)
batch = []

if len(batch) > 0:
self.__index.partial_update_objects(batch)
self.__client.partial_update_objects(self.index_name, batch)

def raw_search(self, query="", params=None):
"""Performs a search query and returns the parsed JSON."""
if params is None:
params = {}
params = SearchParamsObject()

params.query = query

try:
return self.__index.search(query, params)
return self.__client.search_single_index(self.index_name, params)
except AlgoliaException as e:
if DEBUG:
raise e
Expand All @@ -392,7 +398,7 @@ def get_settings(self):
"""Returns the settings of the index."""
try:
logger.info("GET SETTINGS ON %s", self.index_name)
return self.__index.get_settings()
return self.__client.get_settings(self.index_name)
except AlgoliaException as e:
if DEBUG:
raise e
Expand All @@ -405,7 +411,7 @@ def set_settings(self):
return

try:
self.__index.set_settings(self.settings)
self.__client.set_settings(self.index_name, self.settings)
logger.info("APPLY SETTINGS ON %s", self.index_name)
except AlgoliaException as e:
if DEBUG:
Expand All @@ -416,7 +422,7 @@ def set_settings(self):
def clear_objects(self):
"""Clears all objects of an index."""
try:
self.__index.clear_objects()
self.__client.clear_objects(self.index_name)
logger.info("CLEAR INDEX %s", self.index_name)
except AlgoliaException as e:
if DEBUG:
Expand All @@ -430,7 +436,7 @@ def clear_index(self):

def wait_task(self, task_id):
try:
self.__index.wait_task(task_id)
self.__client.wait_for_task(self.index_name, task_id)
logger.info("WAIT TASK %s", self.index_name)
except AlgoliaException as e:
if DEBUG:
Expand All @@ -439,9 +445,9 @@ def wait_task(self, task_id):
logger.warning("%s NOT WAIT: %s", self.model, e)

def delete(self):
self.__index.delete()
if self.__tmp_index:
self.__tmp_index.delete()
self.__client.delete_index(self.index_name)
if self.tmp_index_name:
self.__client.delete_index(self.tmp_index_name)

def reindex_all(self, batch_size=1000):
"""
Expand Down Expand Up @@ -469,6 +475,11 @@ def reindex_all(self, batch_size=1000):
else:
raise e # Unexpected error while getting settings
try:
should_keep_replicas = False
should_keep_slaves = False
replicas = None
slaves = None

if self.settings:
replicas = self.settings.get("replicas", None)
slaves = self.settings.get("slaves", None)
Expand All @@ -483,22 +494,31 @@ def reindex_all(self, batch_size=1000):
self.settings["slaves"] = []
logger.debug("REMOVE SLAVES FROM SETTINGS")

self.__tmp_index.set_settings(self.settings).wait()
set_settings_response = self.__client.set_settings(
self.tmp_index_name, self.settings
)
self.__client.wait_for_task(
self.tmp_index_name, set_settings_response.task_id
)
logger.debug("APPLY SETTINGS ON %s_tmp", self.index_name)

rules = []
synonyms = []
for r in self.__index.browse_rules():
rules.append(r)
for s in self.__index.browse_synonyms():
synonyms.append(s)
self.__client.browse_rules(
self.index_name, lambda _resp: rules.append(_resp)
)
if len(rules):
logger.debug("Got rules for index %s: %s", self.index_name, rules)
should_keep_rules = True

synonyms = []
self.__client.browse_synonyms(
self.index_name, lambda _resp: synonyms.append(_resp)
)
if len(synonyms):
logger.debug("Got synonyms for index %s: %s", self.index_name, rules)
should_keep_synonyms = True

self.__tmp_index.clear_objects()
self.__client.clear_objects(self.tmp_index_name)
logger.debug("CLEAR INDEX %s_tmp", self.index_name)

counts = 0
Expand All @@ -515,18 +535,23 @@ def reindex_all(self, batch_size=1000):

batch.append(self.get_raw_record(instance))
if len(batch) >= batch_size:
self.__tmp_index.save_objects(batch)
self.__client.save_objects(self.tmp_index_name, batch, True)
logger.info(
"SAVE %d OBJECTS TO %s_tmp", len(batch), self.index_name
"SAVE %d OBJECTS TO %s", len(batch), self.tmp_index_name
)
batch = []
counts += 1
if len(batch) > 0:
self.__tmp_index.save_objects(batch)
logger.info("SAVE %d OBJECTS TO %s_tmp", len(batch), self.index_name)

self.__client.move_index(self.tmp_index_name, self.index_name)
logger.info("MOVE INDEX %s_tmp TO %s", self.index_name, self.index_name)
self.__client.save_objects(self.tmp_index_name, batch, True)
logger.info("SAVE %d OBJECTS TO %s", len(batch), self.tmp_index_name)

self.__client.operation_index(
self.tmp_index_name,
OperationIndexParams(
operation=OperationType.MOVE, destination=self.index_name
),
)
logger.info("MOVE INDEX %s TO %s", self.tmp_index_name, self.index_name)

if self.settings:
if should_keep_replicas:
Expand All @@ -536,24 +561,30 @@ def reindex_all(self, batch_size=1000):
self.settings["slaves"] = slaves
logger.debug("RESTORE SLAVES")
if should_keep_replicas or should_keep_slaves:
self.__index.set_settings(self.settings)
self.__client.set_settings(self.index_name, self.settings)
if should_keep_rules:
response = self.__index.save_rules(
rules, {"forwardToReplicas": True}
save_rules_response = self.__client.save_rules(
self.index_name, rules, True
)
self.__client.wait_for_task(
self.index_name, save_rules_response.task_id
)
response.wait()
logger.info(
"Saved rules for index %s with response: {}".format(response),
"Saved rules for index %s with response: {}".format(
save_rules_response
),
self.index_name,
)
if should_keep_synonyms:
response = self.__index.save_synonyms(
synonyms, {"forwardToReplicas": True}
save_synonyms_response = self.__client.save_synonyms(
self.index_name, synonyms, True
)
self.__client.wait_for_task(
self.index_name, save_synonyms_response.task_id
)
response.wait()
logger.info(
"Saved synonyms for index %s with response: {}".format(
response
save_synonyms_response
),
self.index_name,
)
Expand Down
11 changes: 5 additions & 6 deletions algoliasearch_django/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

from django.db.models.signals import post_save
from django.db.models.signals import pre_delete
from algoliasearch.search_client import SearchClient
from algoliasearch.user_agent import UserAgent
from algoliasearch.search.client import SearchClientSync

from .models import AlgoliaIndex
from .settings import SETTINGS
Expand All @@ -13,9 +12,6 @@

logger = logging.getLogger(__name__)

UserAgent.add("Algolia for Django", VERSION)
UserAgent.add("Django", django_version())


class AlgoliaEngineError(Exception):
"""Something went wrong with Algolia Engine."""
Expand All @@ -39,7 +35,10 @@ def __init__(self, settings=SETTINGS):
self.__settings = settings

self.__registered_models = {}
self.client = SearchClient.create(app_id, api_key)
self.client = SearchClientSync(app_id, api_key)
self.client._config.user_agent.add("Algolia for Django", VERSION).add(
"Django", django_version()
)

def is_registered(self, model):
"""Checks whether the given models is registered with Algolia engine"""
Expand Down
4 changes: 2 additions & 2 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ def tearDownClass(cls):
user_index_name = get_adapter(User).index_name
website_index_name = get_adapter(Website).index_name

algolia_engine.client.init_index(user_index_name).delete()
algolia_engine.client.init_index(website_index_name).delete()
algolia_engine.client.delete_index(user_index_name)
algolia_engine.client.delete_index(website_index_name)

def setUp(self):
# Create some records
Expand Down
12 changes: 4 additions & 8 deletions tests/test_engine.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import six
import re

from django.conf import settings
from django.test import TestCase

from algoliasearch.user_agent import UserAgent
from django import get_version as django_version
from algoliasearch_django.version import VERSION
from algoliasearch_django import algolia_engine
Expand Down Expand Up @@ -34,12 +32,10 @@ def test_init_exception(self):
AlgoliaEngine(settings=settings.ALGOLIA)

def test_user_agent(self):
user_agent = UserAgent.get()

parts = re.split("\s*;\s*", user_agent)

self.assertIn("Django (%s)" % django_version(), parts)
self.assertIn("Algolia for Django (%s)" % VERSION, parts)
self.assertIn(
"Algolia for Django (%s); Django (%s)" % VERSION % django_version(),
self.engine.client._config.user_agent.get(),
)

def test_auto_discover_indexes(self):
"""Test that the `index` module was auto-discovered and the models registered"""
Expand Down

0 comments on commit 523958e

Please sign in to comment.