Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Queue Not Logging Failed Tasks with Transactions #41

Open
maniaba opened this issue Apr 1, 2024 · 8 comments · May be fixed by #50
Open

Bug: Queue Not Logging Failed Tasks with Transactions #41

maniaba opened this issue Apr 1, 2024 · 8 comments · May be fixed by #50

Comments

@maniaba
Copy link

maniaba commented Apr 1, 2024

Issue Description:
I have identified a bug in the CodeIgniter 4 queue system. When a task fails during execution, and that task involves a transaction, it fails to log the failure in the designated log file.

class ExampleJob
{
    public function process(string $data):
    {
        $db = db_connect();
        
        $db->transStart(); // Start Transaction
            
       // Job logic here and get RuntimeException

    }
}

When a job fails to execute, the system fails to log the failure in the queue_jobs_failed table. Furthermore, when utilizing the DatabaseHandler, the job record remains unremoved from the queue_jobs table.

This oversight results in a lack of visibility into failed jobs and may lead to potential data inconsistency within the job management system.

@michalsn
Copy link
Member

michalsn commented Apr 1, 2024

I haven't done any testing, but based on your short description, I would say that you should handle possible errors a bit better.

Seems like you started the transaction but never committed it because an exception occurred.

How about something like this?

public function process(string $data):
{    
    try {
        $db = db_connect();
        $db->transBegin();
        
        // Job logic here and get RuntimeException

        if ($db->transStatus() === false) {
            $db->transRollback();
        } else {
            $db->transCommit();
        }
    } catch (\Exception $e) {
        $db->transRollback();
        throw $e;
    }
}

@maniaba
Copy link
Author

maniaba commented Apr 2, 2024

I haven't done any testing, but based on your short description, I would say that you should handle possible errors a bit better.

Seems like you started the transaction but never committed it because an exception occurred.

How about something like this?

public function process(string $data):
{    
    try {
        $db = db_connect();
        $db->transBegin();
        
        // Job logic here and get RuntimeException

        if ($db->transStatus() === false) {
            $db->transRollback();
        } else {
            $db->transCommit();
        }
    } catch (\Exception $e) {
        $db->transRollback();
        throw $e;
    }
}

Thank you for your input. While your proposed solution does indeed handle transaction management within the job processing method, I believe the responsibility for managing transactions during job execution should ideally lie with the queue worker rather than within each individual job's process method.

Handling transactions within the job process method tightly couples transaction management with job logic, potentially leading to code duplication and complexity, especially in scenarios where multiple jobs require transactional operations.

Instead, a more robust approach would be to delegate transaction management to the queue worker itself. This way, transactional concerns can be abstracted away from individual job implementations, promoting cleaner, more maintainable code.

Additionally, by centralizing transaction management in the queue worker, we can ensure consistent error handling and logging across all jobs, simplifying maintenance and reducing the likelihood of oversight or inconsistency.

Therefore, I suggest exploring options to enhance the CodeIgniter 4 queue system to better handle transactional operations and error logging at the worker level, rather than within each job's process method.

Thank you again for your suggestion.

@lonnieezell
Copy link
Member

While we may look into that, I would like to point out that the Queue is not tied to performing database operations, it can be anything, so that sort of functionality may be outside the scope of what the Queue's role is.

In the meantime, though, you could create a custom class you use for all of your database-driven jobs that handles all of that for you and provides the benefits that you're looking for.

@michalsn
Copy link
Member

michalsn commented Apr 2, 2024

Instead, a more robust approach would be to delegate transaction management to the queue worker itself. This way, transactional concerns can be abstracted away from individual job implementations, promoting cleaner, more maintainable code.

Well, that would be quite problematic.

The worker doesn't know what database connection(s) you're using (if any at all as Lonnie mentioned). You may connect to the database even dynamically, without using a config file.

It seems to me that trying to handle this automatically on the worker side would put a lot of strain on performance (and still will not guarantee anything in edge cases), which I would like to avoid.

Personally, I don’t believe this is a good idea, but at the end of the day, this is an open-source project so maybe someone will propose something that will change my mind... although I don't claim a decisive voice in this matter.

@maniaba
Copy link
Author

maniaba commented Apr 2, 2024

I understand your concerns regarding adding database-related functionality to the primary purpose of the queue. I agree that the Queue isn't meant to perform database operations but rather to encompass various types of tasks.

However, the key point I was trying to emphasize is that it's not about the Queue performing database operations but rather about enabling the logging of failed tasks. To have visibility into failed tasks and potentially address data-related issues, there needs to be some mechanism for logging these failures.

@lonnieezell, In that regard, I will consider your suggestion of creating a custom class to be used for all database-related tasks. This could indeed be beneficial for code organization and easier maintenance.

I believe it would be useful to clearly emphasize in the CodeIgniter 4 Queue documentation the importance of handling database transactions appropriately, as failure to commit or rollback a transaction may result in a lack of logging for the reason why a task failed.

Thank you for your suggestions, and I understand your concerns regarding potential performance overhead. I am ready to further discuss this issue and collaborate on finding the best solution for all users.

@kenjis
Copy link
Member

kenjis commented Apr 2, 2024

@maniaba maniaba closed this as not planned Won't fix, can't repro, duplicate, stale Apr 5, 2024
@kenjis kenjis reopened this Apr 5, 2024
@kenjis
Copy link
Member

kenjis commented Apr 5, 2024

That is not the same as the Issue that posted, but if the above behavior is confirmed, it is a serious bug.
So I reopened for now..

@michalsn michalsn linked a pull request Sep 23, 2024 that will close this issue
5 tasks
@michalsn
Copy link
Member

This is a valid point. I addressed it here: #50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants