Problem/Motivation

Drupal CMS (aka Starshot) has a Search Track. The search recipes that will be suggested to all Drupal CMS users will include search api module and some other modules from its ecosystem (search_api_exclude, search_api_autocomplete, facets, maybe others in the future).

Config Actions are fundamental part of the recipes. It would be much easier to perform various operations with search api index and search api server if there were config actions for that. The obvious examples of what is needed would be add/remove/rename field from search index, add/remove/update processor, etc .

Drupal core >= 10.3 allows easy implementation of config actions for config entity class methods as ActionMethod. This allows to expose the class methods as config actions. This can already help while not producing any extra code, just expose some methods of search api index/server classes as action methods.

I would like to start a discussion here, what methods should be marked as action methods. And what other config actions can be created to help integrate Search API with recipes. Ideally, all operations that site builder needs to do to make search work on the site would be nice to have as action, but we should start from something.

Remaining tasks

  1. Create a plan of what methods should/could be exposed as config actions.
  2. Create list of other useful actions that can be added as config action plugins.

Comments

a.dmitriiev created an issue. See original summary.

a.dmitriiev’s picture

I think the following methods from Index entity class should be exposed as config actions:

  • setOption (without plural support, as there is already setOptions method in the class)
  • setOptions
  • removeDatasource as only the id is needed for argument
  • removeProcessor
  • renameField
  • removeField

it would be also nice to have the following methods exposed, but some code adjustments will be needed:

  • addDatasource, but at the moment the argument is of type Datasource and it can't be used in recipe. Maybe alternatively there could be a method addDatasourceByIdAndConfig that will have datasource id and its config as arguments.
  • setTracker has and object as argument so it can't be used as action method, but maybe having a method setTrackerByIdAndConfig with tracker plugin id and config as arguments would make sense
  • The same for setServer it makes sense to create setServerById?
  • addProcessor has object as argument, but maybe new method addProcessorByIdAndConfig would be ok to add as well
  • addField has Field object as argument, but maybe new method addFieldByFieldConfig would be ok to add

Methods that are not in Index class yet, but might be useful:

  • setServer
  • setReadOnly

Methods for Server entity:

  • setBackendConfig

Missing methods on Server entity, that could be useful:

  • setBackend - as setBackendConfig method assumes that backend property is already set, maybe it is needed to have backend set method as well.
a.dmitriiev’s picture

Issue tags: +Starshot, +Recipes initiative
a.dmitriiev’s picture

I have prepared the first MR for recipe integration https://www.drupal.org/project/search_api/issues/3484304 . It exposes only already existing methods as config actions to start this feature rolling.

borisson_’s picture

I have prepared the first MR for recipe integration https://www.drupal.org/project/search_api/issues/3484304 . It exposes only already existing methods as config actions to start this feature rolling.

This is a good and easy first step, I think that one is ok.

  • addDatasource, but at the moment the argument is of type Datasource and it can't be used in recipe. Maybe alternatively there could be a method addDatasourceByIdAndConfig that will have datasource id and its config as arguments.
  • setTracker has and object as argument so it can't be used as action method, but maybe having a method setTrackerByIdAndConfig with tracker plugin id and config as arguments would make sense
  • The same for setServer it makes sense to create setServerById?
  • addProcessor has object as argument, but maybe new method addProcessorByIdAndConfig would be ok to add as well
  • addField has Field object as argument, but maybe new method addFieldByFieldConfig would be ok to add

For datasource, and server I think adding a new method is a good idea.
Processors and fields are more difficult, because their configuration can be more extensive, but I guess we can go through the same way here as well?

I think tracker is probably not needed, since for 99% the basic tracker is used. So I'm not sure how I feel about creating this new method, however if we already do this same trick for the other 4 I guess it's not too bad?

drunken monkey’s picture

Great initiative, thanks! I already merged your first MR, just making existing methods available seems like a low-hanging fruit.

My thoughts on the rest of your suggestions:

  • setServerById(): I would just call that setServerId() maybe? Would seem like a natural extension from the existing getServerId(). It’s just a bit unfortunate that getServerInstance() and setServer() don’t follow this sensible pattern.
  • addDatasourceByIdAndConfig(): We already added a separate config action plugin for that in #3456728: Create a config action to add a data source to an index. However, if we add new methods for the other plugin types, doing it for datasources would also make sense for the sake of consistency – not sure how to handle that, we probably don’t want to offer two config actions for the exact same thing.
  • setTrackerByIdAndConfig(), addProcessorByIdAndConfig(), addFieldByFieldConfig: I admit I first balked a bit at thes suggestions, as I dislike such verbose method names and the methods would pretty much duplicate existing ones. I therefore wanted to suggest instead adding dedicated config action plugins to implement this functionaliy, as we already have for datasources (see above).
    However, on the other hand it does seem a bit strange to have something available to site admins but not to developers. Also, I suspect the DX of those new methods would be better anyways than of the existing ones – I would now say we probably went the wrong way there when first writing the D8 version of the module.
    So, I guess I’m now on board with just adding those methods. I can also imagine our own code subsequently drifting towards using those new methods. They certainly seem handier in most situations. (Though the lack of dependency injection for entities continues to be vexing in this regard.)
    As mentioned above, though, we should think about what to do with datasources. We will probably want to add the addDatasourceByIdAndConfig() method in any case, but maybe just not make it available as a config action?
  • setBackend(): This would be a major architectural change as a server’s backend plugin is currently immutable. I would therefore need a very good argument why this would be helpful/needed before considering it.
  • setReadOnly(): Yes, good idea. No clue why this is currently missing.

Note that these should all also be added to the interface, in my opinion, which means you’ll have to add them to the UnsavedIndexConfiguration class, too. (Just as a tip, as I regularly forget that as well.)

Methods that are not in Index class yet, but might be useful:

  • setServer
  • setReadOnly

setServer seems like a typo, as that method already exists (and is listed by you a few lines above). Do you know what you meant?

mxr576’s picture

Two additional action suggestions:

  • Index items - with optional data source filtering. Also useful when default content import doesn't trigger indexing automatically - haven't checked to root cause but experienced this when I wrote a test for a recipe
  • Assign index to search backend - for recipes that bundle indexes without backends. Should filter by server type (e.g., Solr) with fallback option to prevent exception when a match not found.
borisson_’s picture

I agree with the second one; that sounds useful. The first one however (index items) seems like it shouldn't be happening at all?

mxr576’s picture

Well, I guess the answer is "it depends". Whoever uses that action should be awareof consequences. However without that it is complicated to set up an immediately usable demo env with recipes, where waiting for cron to index items may not be an option.

strykaizer’s picture

clayfreeman’s picture

Would also be useful to have actions to manage data source bundle includes/excludes, and add/remove type-specific boosts.

Consider the example where someone wants to deliver their search configuration and content types in separate recipes:

config:
  actions:
    search_api.index.content:
      addIncludedBundle: landing_page
      addBundleBoost:
        bundle: landing_page
        value: 5.0

Plural variants would be a nice bonus!

drunken monkey’s picture

@clayfreeman:

Would also be useful to have actions to manage data source bundle includes/excludes, and add/remove type-specific boosts.

That seems a bit too specific to add at this point, when it’s not even possible yet to add fields to an index.

Moreover, I’m not sure how this would work on an architectural level, as the bundle includes/excludes are options specific to the datasource plugin. I don’t think we can/should provide an index-level action to modify these. (Same for the bundle boosts, which is a specific processor plugin.)
Not sure, is there a clean way to provide a config action specific to a certain plugin associated with the entity?