Feedback

Feedback Processing Service

Processing

What is the Feedback Processing service?

The Feedback Processing service is responsible for analyzing feedback by executing a set of predefined processes called executors. Each feedback item goes through a sequence of analyses, and once all assigned executors have completed, the feedback is considered fully processed.

Executors are organized into execution groups using a group_order column. This allows defining ordered groups of processes where:

  • Executors in the same group (group_order = N) run in parallel.
  • The next group (group_order = N+1) starts only if all executors from the previous group have completed successfully.

This mechanism enables more advanced workflows and dependencies between processes, ensuring that certain analyses only start once prerequisite steps are validated.

A central ProcessManager handles the orchestration:

  • Executors are dispatched asynchronously via Laravel's job system.
  • It ensures group-level execution integrity by waiting for all processes in the current group before moving to the next one.

Important Information

If any executor in a group fails, the next group will not be triggered for that feedback. This guarantees a controlled and ordered flow of analysis.

Using the ProcessManager

To execute the processing for a given feedback instance, instantiate and call the handle() method on the ProcessManager:

use App\Services\Feedback\Processing\ProcessManager;
use App\Models\Feedback;

$feedback = Feedback::find(1); // Retrieve a feedback instance

(new ProcessManager($feedback))->handle();

If you need to run only specific processes, you can pass an array of allowed executors:

(new ProcessManager($feedback, ['alpha-score']))->handle();

This ensures that only the specified executor(s) will be executed for the given feedback item.


Executors

What is an executor?

An executor is a unit of processing logic that performs a specific analysis on a feedback item or a related model. Executors implement the Executable interface and must define:

  • A name to identify them.
  • The model they apply to.
  • Whether they are applicable to a given model instance.
  • Their execution type (e.g., one-time or always).
  • The logic for execution.

Executors are stored in app/Services/Feedback/Processing/Executors/.

Registering an Executor

Every executor must be registered in config/feedback.php under the executors key. If an executor is not registered, it will not be recognized by the system.

Example configuration:

'executors' => [
    Processing\Executors\SanitizerExecutor::class,
    Processing\Executors\NpsProfileExecutor::class,
    Processing\Executors\AlphaScoreExecutor::class,
],

Create a new executor

Implementation

To create a new executor, extend the Executor abstract class and implement the required methods.

namespace App\Services\Feedback\Processing\Executors;

use App\Services\Feedback\Processing\Executor;
use Illuminate\Database\Eloquent\Model;

class CustomExecutor extends Executor
{
    public static function name(): string
    {
        return 'custom-executor';
    }

    public static function model(): string
    {
        return Feedback::class;
    }

    public static function applicable(Model $model): bool
    {
        return true; // Define the condition for applicability
    }

    public function execute(Model $model): void
    {
        // Execution logic here
    }
}

Execution Type

Executors must define their execution type using the executions() method:

public static function executions(): ExecutionsEnum
{
    return ExecutionsEnum::ONE_TIME; // or ExecutionsEnum::ALWAYS
}
  • ONE_TIME: The executor runs only once per model instance, even if ProcessManager is called multiple times.
  • ALWAYS: The executor runs every time ProcessManager is executed.

Applicable

The applicable() method determines whether an executor should process a given model instance. If it returns false, no job will be dispatched. This acts as a filtering mechanism.

For example, the Alpha Score calculation applies only to QuestionAnswer models of type textarea. If the condition is not met, the method returns false:

public static function applicable(Model $model): bool
{
    return $model->question?->type === QuestionTypeEnum::TEXTAREA->value;
}

Model

Each executor is associated with a specific model by defining the model() method. This model must be either the Feedback model itself (Feedback.php) or one of its related models.

The available relations are defined in config/feedback.php:

'model' => \App\Models\Feedback::class,

'relations' => [
    'questionAnswers' => \App\Models\QuestionAnswer::class,
    'attributeValues' => \App\Models\AttributeValue::class,
],

Thus, an executor can be associated with:

  • Feedback::class → The executor will run once per feedback.
  • QuestionAnswer::class or AttributeValue::class → The executor will run independently for each related QuestionAnswer or AttributeValue of the feedback.

Configurations

Executor-specific configurations are stored in config/feedback.php under the configurations key. Each executor has its own configuration set, for example:

'configurations' => [
    Processing\Executors\AlphaScoreExecutor::class => [
        'url'     => env('FEEDBACK_ALPHA_SCORE_URL', 'http://91.134.77.15:8000/predict'),
        'api_key' => env('FEEDBACK_ALPHA_SCORE_API_KEY'),
    ],
],

Executors can retrieve these configurations using the configurations() method.


Commands

Pause or resume an executor

Executors can be enabled or disabled using CLI commands:

php artisan feedback:processing:enable
php artisan feedback:processing:disable

Create or delete an executor

To create or delete an executor:

php artisan feedback:processing:create
php artisan feedback:processing:delete

title: Start Feedback Processing


Start Feedback Processing

The feedback:processing:start command interactively starts the processing of feedback using various filters and execution settings. It allows you to define the scope of feedback to process, date range filters, which processes to run, and whether to reset already existing process steps.


Database Structure

The system uses two main tables to track processes:

feedback_processes

Stores information about available executors:

ColumnTypeDescription
idbigintUnique identifier
executor_namevarchar(255)Executor name
enabledtinyint(1)Whether the process is active
created_attimestampCreation timestamp
updated_attimestampLast update timestamp

feedback_process_steps

Tracks the execution status of processes for each feedback item:

ColumnTypeDescription
idbigintUnique identifier
process_idbigintRelated process ID
feedback_idbigintFeedback item ID
processable_typevarchar(255)The model type being processed
processable_idbigintThe specific record being processed
statusvarchar(255)Execution status (e.g., pending, completed)
dispatchesintNumber of dispatch attempts
attemptsintNumber of execution attempts
last_error_messagelongtextStores the last encountered error
created_attimestampCreation timestamp
updated_attimestampLast update timestamp

This database structure allows tracking each executor's progress and debugging failures efficiently.


This documentation provides a structured guide to understanding, implementing, and managing the Feedback Processing service in Feedier.

Previous
Notifications
Next
Import