Notify users PDF creation is ready and can be downloaded - ruby-on-rails

Users can create a PDF in my app which takes some time to generate, so it has to be done in a background job. No problem, but then there is a delay and the user must be notified that the PDF is ready.
So the first choice is to send an email with a download link or a push notification in the app itself. My preference is the push notification, so I guess ActionCable is the way to go? My app runs on Heroku, so is ActionCable also a good choice then or is another solution preferable?
Then there is another consideration, where to store the generated PDF until the user downloads it? I could upload it to Azure/S3/etc with ActiveStorage, or I could store it temporarily in an app folder and delete it after download. My preference is to do the last, because the PDF is there only for a few minutes and therefore the hassle to store it in the cloud is not really needed?

You have a very broad question here, which is very much dependent on the overall user needs and experience you want them to have.
I'll start with the simplest part, in terms of temporary storage of the PDF. There are several things to bear in mind here.
I would say that from a scalability, and application security standpoint, storing the PDF to the cloud is the way to go. Opening up writable directories on your application server carries a risk. Also, if you ever need to scale to more than one server, this will not work. Deleting items from cloud storage is not hard with the appropriate APIs.
Is it essential for the user to be authenticated in some way to download the PDF? This is more challenging if you push the PDF to a cloud bucket (unless you have the PDF named with a very complex, unguessable name, that name only accessed through the authenticated application). If the data is less sensitive, then your email notification can show the link directly, but you won't know easily if a user has retrieved the PDF and it is now ready to be deleted.
In terms of notification, I'd go with email for several reasons. Simplicity is the main one. Do you have experience with ActionCable? It appears simple on the surface, but there are many things to bear in mind when using it: infrastructure and UI being the major ones. Also, from a user experience perspective, are users likely to hang around in the application waiting for the PDF to be completed? What happens if they logout? How will they know the PDF is available?
If the timescale for generation of the PDF is short and absolutely optimized scalability is not a big deal, you could consider a simpler mechanism that checks for user notifications (a simple query onto a user_notifications table for example) for every user action, and use a flash or some other session flag that the UI can check and use to asynchronously retrieve the notification.
Just ideas. Impossible to give definitive answers.

Related

Where to save my iOS app's save files

I am learning iOS file system to store my game data like saving the amount of money earned and things like this in a xml file.
The question is where should I store them?
I read this: File System Basics
And I don't know that I should save data in Documents directory or Application Support directory.
Because the data I want to save is something that is not associated with user's documents and user will never see it so it should be in Application Support, but on the other hand it's something that is affected by user interactions so it should be in Documents.
I think it is the Application Support/MyGame as per the Apple Developer guide link shared by you. You are confused by the fact that it should not be something affected by user interaction. Actually it means user should not directly interact with these. See this from the link: File System Basics
Using something like Parse may slow down your app as it needs to interact with their server, but you do get a backup.
For something of this size, I'd use a mobile backend solutions provider like Parse or Firebase. Personally I use Parse in my projects and is very easy to implement advanced functionality into your apps like user registration/save data to users.
Hope this helps.

Mvc azure storage, auto delete storage after certain time

Im developing a azure website where users can upload blob and metadata. I want uploaded stuff too be deleted after some time.
The only way i can think off is going for a cloudapp instead of a website with a worker role that checks like every hour if the uploaded file has expired and continue and delete it. However im going for a simple website here without workerroles.
I have a function that checks if the uploaded item should be deleted and if the user do something on the page i can easily call this function, BUT.. If the user isnt doing anything and the time runs out it wont delete it because the user never calls the function.. The storage will never be deleted. How would you solve this?
Thanks
Too broad to give one right answer, as you can solve this in many ways. But... from an objective perspective because you're using Web Sites I do suggest you look at Web Jobs and see if this might be the right tool for you (as this gives you the ability to run periodic jobs without the bulk of extra VMs in web/worker configuration). You'll still need a way to manage your metadata to know what to delete.
Regarding other Azure-specific built-in mechanisms, you can also consider queuing delete messages, with an invisibility time equal to the time the content is to be available. After that time expires, the queue message becomes visible, and any queue consumer would then see the message and be able to act on it. This can be your Web Job (which has SDK support for queues) or really any other mechanism you build.
Again, a very broad question with no single right answer, so I'm just pointing out the Azure-specific mechanisms that could help solve this particular problem.
Like David said in his answer, there can be many solutions to your problem. One solution could be to rely on blob itself. In this approach you can periodically fetch the list of blobs in the blob container and decide if the blob should be removed or not. The periodic fetching could be done through a Azure WebJob (if application is deployed as a website) or through a Azure Worker Role. Worker role approach is independent of how your main application is deployed. It could be deployed as a cloud service or as a website.
With that, there are two possible approaches you can take:
Rely on Blob's Last Modified Date: Whenever a blob is updated, its Last Modified property gets updated. You can use that to identify if the blob should be deleted or not. This approach would work best if the uploaded blob is never modified.
Rely on Blob's custom metadata: Whenever a blob is uploaded, you could set the upload date/time in blob's metadata. When you fetch the list of blobs, you could compare the upload date/time metadata value with the current date/time and decide if the blob should be deleted or not.
Another approach might be to use the container name to be the "expiry date"
This might make deletion easier, as you then could just remove expired containers

Letting visitors try out user-only features that write to DB

My site lets people create database entries (which most rails apps do), and I realized that there's a huge drop-off from landing on the site to actually signing up to try it. Basically the service lets users build their own document by combining different components. I'm thinking about adding an interface where visitors who are not yet registered can try out the features (building stuff) and ask them to sign up at the last stage, when they're about to publish their document.
First thing that comes to mind is use HTML5 local storage, but then another idea came to mind: maybe I could create a temporary user whenever a visitor tries out the features, and then later remove them from the database if they don't sign in. I'm not sure if this is safe, but this seems like it might be easier than dealing with all the local storage issues.
What would be the best practice for this type of situation?
HTML5 storage would be an option, tho most likely a lot of client side coding.
Other options would be to have a duplicate table of these 'demo' documents which you can clear every now and again for users that did not sign up. You could also just store the document in the user session, as you don't need it permanently stored, and then store it in the database once they have signed up.

background file uploader?

So after two days of googling incessantly and apparently asking the wrong questions, I think I have figured out a way to word it so I get the response I'm looking for.
I have a Project Management application, written in MVC3. Sometimes, the users have to attach large files and upload them to the applications. (100-200 mb) is typical. The problem of course is that this is currently handled synchronously, and varying network speeds mean that the application can be completely blocked for 10 minutes to an hour if someone's on a slow connection. FTP is NOT an option here (my hands are tied by our network guys on that one).
So I am looking for a way to do the following workflow:
user clicks Upload File
user selects File to upload
user clicks "Go" or whatever button
Application says "your file is being uploaded. You will be notified when it's complete"
user continues to use the application as normal.
Some things to be aware of: I already have an internal messaging system implemented. So when I say that the app will notify the user when it's complete - all it needs to do is insert a new message into the queue. It DOES NOT need to notify the user's current screen or anything like that - so I'm not worried about a return value of any kind. I also have a background Error log implemented, so I can insert a message into the log if something goes wrong and again - inform the user via the internal messaging system.
So I am stumped on how to implement this. I thought an Async Controller was the right way to go, but if I understand all the stuff I've been seeing - it's not. Feel free to correct me. I implemented a version using Async but when addressing the one problem it had, I was informed that I was doing it wrong anyway.
So uh...help? I'm all ears.
If you can use 3rd party controls then take a look at the Telerik controls:
http://www.telerik.com/products/aspnet-mvc/upload.aspx
It has an Asynchronous File Upload control.

How Can I Verify A Download Has Been Completed?

We're using ASP.NET MVC and our action does this:
pull records from DB
mark records as downloaded
push zipped download to browser
Now the problem comes when the download doesn't complete for some reason - maybe the user clicks "Cancel" or IE pops up that download security bar. I'm wondering if there's an alternative solution.
Could we push the download to the user and then only mark records as downloaded when we're sure they've received the right number of bytes? I have to say that I'm struggling with this one and a solution which is as easy for end users as possible would be fantastic.
There isn't any reliable way to do this without a process running on the client which can verify the transfer completed. Of course, the only process we can reasonably expect the user to already have, or be willing to install, is Flash.
Only Flash 10 supports saving files directly to disk as the user requests. (Previous versions had a "shared object" which was kind of like a very large cookie space more than anything else - not for transferring files but saving reusable application data). Read up here for info on how to interact with the end-user's filesystem via Flash 10.
Essentially there is a method call save() which will push data to a location of the user's choosing. The specific location is hidden from your code; for obvious security reasons, you merely push the file into a black box and Flash handles the rest.
The only real bit of info missing here is how to get your file into the Flash player, but anyone with a little Flash experience should have no trouble figuring that out with a few minutes of research. Without Flash experience you should still have it working in under a day.
Rather than simply redirecting the user to the resource that is to be downloaded (there by causing the popup of would you like to download a file) you might try to two things. Push the resource out of a page as a byte array. Once the download has completed redirect the download page to another page. On this page you can then add to your workflow asking if the download went ok or not. Also, if they got this far you could assume (ass-u-me) that it worked. To actually track how far the download got I don't think is doable as you have nothing on the other end monitoring bytes received.
I don't believe there is. If this is necessary you may need to utilize a Silverlight (Or flash) control in conjunction with your application.
Basically the approach with either one would be to open a socket connection to the HTTP url and save it to the appropriate path on the User's drive. Once the download is complete you could have the control generate a hash value from the file and send that back to some ASP page. If the hash value is never submitted or is incorrect you know they didn't finish the file.
Even checking that all the bytes were sent doesn't really guarantee anything:
The user might still cancel the download before saving it, or their browser might crash, etc.
The recipient might not be the user. It might be a proxy server with a virus scanner that decides to block the transfer, etc.

Resources