i960's avatar
Level 3

Send queued command job results back to user

So I have a section of my app that allows users to upload multiple images. I have a class that handles this process, and it first generates a new hashed file name, saves the image to local storage temporarily, saves the image name/path to the DB along with the user it belongs to, and then hands off processing of the image to a queued command.

From there, the command will resize the image if needed, upload the image to S3, delete the temporary file, and then fire an event that the image was uploaded. Right now the event does nothing, it's there for future use.

On the users end, after submitting the form, they are redirected back to the same form where the images will show up. If I use a sync'd queued command, then the browser will sit and wait for the entire upload to S3 process is complete before the redirect, and then the page will load and the images show. But in production, I will be using the database sync driver. I want the user to be redirected back immediately, and have the resize and upload process be handled in the background. That all works great, except if the user is redirected before the upload is complete (sometimes it takes seconds, but occasionally it can take up to a minute if it's a large file and S3 is being slow), then the user will see a broken image.

What I want is for the page to somehow know that the upload is not finished, and display a "processing image" placeholder, then as soon as the queued job is complete and the event is fired, the image loads automatically without the user having to refresh the page. In other words, I don't know how to send a delayed response back to the users browser and have something happen on screen. I'm guessing it will require some sort of jquery magic, but I'm not sure.

A perfect example of something like this in action is Envoyer. If you watch the screen casts, you'll see that during the deployment process, each step will display a spinning icon while it's waiting for the step to complete, and as soon as the step finishes, it updates with a complete message. I know how to post a form via ajax and wait for a response, but this is the opposite I think. I want the fired event to trigger something that updates the screen. Any ideas?

0 likes
4 replies
sitesense's avatar
Level 19

Hi @i960 I had a similar problem myself recently. I also created an event to be fired when each job completes.

In my event handler, I create a notification which in my case, I save to a database table that I created for notifications. You could even use a session I suppose.

On the page that is waiting for the notification, I simply use ajax to keep calling a method that reads my notifications in the db and changes a div with the notification message.

EDIT: Here's my Ajax if it might help. $('#ajaxRefresh').on('click', is just a button I click to show progress.

var timeoutId = null;
            $('#ajaxRefresh').on('click', function(event) {
                event.preventDefault();
                $('i.fa-refresh').toggleClass('fa-spin');
                if ($( "i.fa-refresh").hasClass('fa-spin')) {
                    $('#ajaxRefresh').html('<i class="fa fa-refresh fa-spin"></i> Hide Progress');
                    showProgress();
                } else {
                    $('#ajaxRefresh').html('<i class="fa fa-refresh"></i> View Progress');
                    clearTimeout(timeoutId);
                }
                $("#progress").toggleClass('hide');
            });

            function showProgress() {
                var progress = $.ajax({
                    type: 'GET',
                    url: '{{ route('ajaxResults') }}',
                    async: false
                }).complete(function() {
                    timeoutId = setTimeout(function() {
                        showProgress();
                    }, 5000);
                }).responseText;
                //alert(progress);
                $("#progress").html(progress);
            }
i960's avatar
Level 3

@sitesense That is exactly what I was thinking I might have to do. However, I realized that laracasts also has a similar feature. Whenever someone replies to a thread and you are looking at the thread, a notification pops up letting you know. So I looked at the page source to figure out how. Jeffrey is using Pusher (https://pusher.com/) to pull this off. After looking at it briefly, it seems like it's perfect for what I need.

The only question I have is on the pricing. The sandbox plan seems like it should be plenty for my needs. However, I don't know exactly what a "connection" means. On the sandbox you get 20 max simultaneous connections. Does that mean if 20 users are all looking at a page that has Pusher loaded waiting for notifications, that it will consume 20 connections?

@JeffreyWay care to chime in? It seems like if that were the case, you would be consuming a rather large number of connections for laracasts. So maybe I'm misunderstanding. I only expect a few dozen users per day actively uploading images.

i960's avatar
Level 3

@sitesense I just saw your update with code. I might actually try that first before doing something like Pusher. Thank you!

sitesense's avatar

@i960 you're welcome :)

I was going to look into something like Pusher myself too when I get a bit of time. I'd rather not pay though lol, it can't be that difficult surely?

Please or to participate in this conversation.