Repository: algolia/algoliasearch-client-go
Pull request #730 (2023-05-05 16:04:22)

feat(recommend): implement Recommend-level waitTask
| Q                 | A
| ----------------- | ----------
| Bug fix?          | no
| New feature?      | yes    <!-- please update the /CHANGELOG.md file -->
| BC breaks?        | no     
| Need Doc update   | no

## Describe your change

Support waiting tasks with a Recommend-level scope. It is slightly different than the index-level task because it expects a model name in the URL. Note that this is historical though, the model name is now useless and both index-level and recommend-level actually work similarly behind the hood.

## What problem is this fixing?

Add the abillity to build recommend rules in Metis.


Patch:
diff --git a/algolia/search/index.go b/algolia/search/index.go
index 58d80928..98021a30 100644
--- a/algolia/search/index.go
+++ b/algolia/search/index.go
@@ -41,7 +41,16 @@ func (i *Index) path(format string, a ...interface{}) string {
 // Algolia engine.
 func (i *Index) WaitTask(taskID int64, opts ...interface{}) error {
 	return waitWithRetry(func() (bool, error) {
-		res, err := i.GetStatus(taskID, opts...)
+		var res TaskStatusRes
+		scope, err := getScopeFromTaskID(taskID)
+		if err != nil {
+			return true, err
+		}
+		if scope == "recommend" {
+			res, err = i.GetRecommendStatus(taskID, opts...)
+		} else {
+			res, err = i.GetStatus(taskID, opts...)
+		}
 		if err != nil {
 			return true, err
 		}
@@ -101,6 +110,16 @@ func (i *Index) GetStatus(taskID int64, opts ...interface{}) (res TaskStatusRes,
 	return
 }
 
+// GetRecommendStatus retrieves the task status according to the Algolia engine
+// for the given Recommend task.
+func (i *Index) GetRecommendStatus(taskID int64, opts ...interface{}) (res TaskStatusRes, err error) {
+	// modelName is arbitrarily defined as related-products because this parameter does not matter anymore
+	modelName := "related-products"
+	path := i.path("%s/task/%d", modelName, taskID)
+	err = i.transport.Request(&res, http.MethodGet, path, nil, call.Read, opts...)
+	return
+}
+
 // Exists returns whether an initialized index exists or not, along with a nil
 // error. When encountering a network error, a non-nil error is returned along
 // with false.
diff --git a/algolia/search/utils.go b/algolia/search/utils.go
index 42eb123e..e207b393 100644
--- a/algolia/search/utils.go
+++ b/algolia/search/utils.go
@@ -101,3 +101,19 @@ func hasObjectID(object interface{}) bool {
 	_, ok := getObjectID(object)
 	return ok
 }
+
+func getScopeFromTaskID(taskID int64) (string, error) {
+	scopeID := (taskID / 10) % 100
+	switch scopeID {
+	case 0:
+		return "index", nil
+	case 1:
+		return "app", nil
+	case 2:
+		return "metis", nil
+	case 3:
+		return "recommend", nil
+	default:
+		return "", fmt.Errorf("invalid taskID scope")
+	}
+}


Test patch:
diff --git a/algolia/search/utils_test.go b/algolia/search/utils_test.go
index 47809450..b77fab17 100644
--- a/algolia/search/utils_test.go
+++ b/algolia/search/utils_test.go
@@ -53,3 +53,19 @@ func TestHasObjectIDField(t *testing.T) {
 
 	require.False(t, hasObjectID(nil))
 }
+
+func TestGetScopeFromTaskID(t *testing.T) {
+	for _, c := range []struct {
+		taskID        int64
+		expectedScope string
+	}{
+		{4001, "index"},
+		{4011, "app"},
+		{4021, "metis"},
+		{4031, "recommend"},
+	} {
+		scope, err := getScopeFromTaskID(c.taskID)
+		require.NoError(t, err)
+		require.Equal(t, c.expectedScope, scope)
+	}
+}