What happens when multiple processes try to write the same file? - ruby-on-rails

Due to a limitation of a 3rd party library, I need to use a file with a static name. What happens in Rails if multiple users are trying to write to that file at the same time? EACCESS error?
Is there a way I could circumvent this?

At the Ruby level, what will happen if multiple processes try to write to the file depends on how the library uses the file: whether and how it locks the file before opening it and what mode it opens the file in. It might just work, it might raise an error, or (most likely, if the library does nothing to handle this situation) multiple writers might silently interleave writes with one another in a way that could corrupt the file, or the last writer might win.
At the Rails level, it depends on how you run Rails. If you run a single, normally configured Rails instance on a given server, you won't have any problems, since Rails itself is single-threaded by default. If you run multiple Rails instances (presumably controlled by an application server like Passenger or unicorn) you might have problems.
Assuming the library doesn't handle multiple writers for you, you can work around it in a couple of ways:
Run only one instance of your Rails app on each server (or docker container or chrooted environment).
Fork the library and change it to include the process ID in the file name. That's what I'd do.

Related

Does a Rails console get it's own hardware thread?

In my Ruby/Rails app (using the default interpreter), I don't believe I've configured anything to make it use multiple threads. But I'm wondering how does this impact opening up a rails console to a production server that's handling regular traffic? Is rails giving my console its own hardware thread that's being used to execute my commands? Does this mean I have to worry about thread safety when modifying mutable storage via the console, say for example a file on disk?
When you start the rails console it loads a completely separate copy of your application from the server. The only thing they share is the database. So, thread safety isn't an issue, but you might still need to be mindful of accessing/mutating shared resources like database records or files.

Ruby on Rails - How can I run automated tests on a user-uploaded Ruby file?

I'm currently working on a Rails application (React frontend) that deals with students submitting zipped directories of Ruby projects. The files are stored through Paperclip and S3 on an Assessment model. Currently, in order to grade student submissions, I must download every student file and test with RSpec individually from the command line.
I've improved the workflow through writing a command line script (in Ruby) that will take a directory of Zips, grade them all at once, and store each individual RSpec output in a scores.txt file.
The goal is to allow students to upload their .zips through a portal, and have them be immediately and automatically tested with RSpec. Is there a way to do this?
I've done a lot of searching, and so far can only find advice on how to test live user input (similar to codecademy, or other sites with integrated IDEs).
Sure this is doable.
Unzip the file, load each file and run tests on the defined methods/classes.
But there are at least two things to consider...
Security
A student could overwrite your test method to return only good grades, or random or whatever. Because you're basically loading their code into the same process that grades them. You can, of course, make the method names not obvious but security through obscurity is just crossing your fingers and hope to be lucky (e.g. a student can make a script that uploads your source code somewhere to inspect later)
I'd solve it with a small API that takes the code, the source file, method to call and returns the output. So instead of loading the file in your space - you ask a separate app to produce output, and in your main app would evaluate/grate it.
Consistency of results
i.e. one student could overwrite definition of Object.to_s and others would use it thinking it's the original implementation - thus making their code failing in producing the desired output.
Solution to this one would be to run each test in a separate process (not just thread)
This unfortunatelly brings us back to security - each script will be able to read and alter the code that's accessible by the app that runs it.
So! What to do then?
The easiest thing I can think of right now is to start a container (i.e. docker, rocket or other) and run the code there. An additional benefit would be that you can share the container image with the students, and they can run their code in the same environment making the results as consistent as you can imagine.

How to 'safely' back up SQLite3 in Rails?

I'm currently developing a small-scale web app using Rails, and have been looking into the best way to go about keeping backups of the database. I've decided to use SQLite3 for the database as it's small-scale enough that it makes sense (there will ideally be barely any traffic to the website), but as the application needs to be accessible on-demand 24/7, I want to make sure that any backup method doesn't interrupt things too much.
I've found a fair few old resources online that suggest just copying the database file, but this has obvious locking problems if the file is written to whilst the copy happens. The SQLite built-in .backup command seems to be what I'm after to avoid this, but I can't seem to find a way to trigger that properly from within Rails. Using the ActiveRecord connection.execute('.backup') doesn't work because it's not valid SQL syntax, and whilst there are appropriate methods to call the backup from inside the SQLite3 gem, I'm not sure if it's possible to get down to that object level from within ActiveRecord?
I could just set up a cron job/script that runs the sqlite command-line tool and executes the backup command, but I'm worried that running that concurrently with the Rails server could still potentially present concurrency issues?

Multiple redmine instances best practices

I'm studying the best way to have multiple redmine instances in the same server (basically I need a database for each redmine group).
Until now I have 2 options:
Deploy a redmine instance for each group
Deploy one redmine instance with multiple database
I really don't know what is the best practice in this situation, I've seen some people doing this in both ways.
I've tested the deployment of multiple redmines (3 instances) with nginx and passenger. It worked well but I think with a lot of instances it may not be feasible. Each app needs around 100mb of RAM, and with the increasing of requests it tends to allocate more processes to the app. This scenario seems bad if we had a lot of instances.
The option 2 seems reasonable, I think I can implement that with rails environments. But I think that there are some security problems related with sessions (I think a user of site A is allowed to make actions on site B after an authentication in A).
There are any good practice for this situation? What's the best practice to take in this situation?
Other requirement related with this is: we must be able to create or shut down a redmine instance without interrupt the others (e.g. we should avoid server restarts..).
Thanks for any advice and sorry for my english!
Edit:
My solution:
I used a redmine instance for each group. I used nginx+unicorn to manage each instance independently (because passenger didn't allow me to manage each instance independently).
The two options are not so different after all. The only difference is that in option 2, you only have one copy of the code on your disk.
In any case, you still need to run different worker processes for each instance, as Redmine (and generally most Rails apps) doesn't support database switching for each request and some data regarding a certain environment are cached in process.
Given that, there is not really much incentive to share even the codebase as it would require certain monkey patches and symlink-magic to allow the proper initialization for the intentional configuration differences (database and email configuration, paths to uploaded files, ...). The Debian package does that but it's (in my eyes) rather brittle and leads to a rather non-standard system.
But to stress again: even if you share the same code on the disk between instances, you can't share the running worker processes.
Running multiple instances from the same codebase is not officially supported by Redmine. However, Debian/Ubuntu packages seem to support such approach... See:
Multiple instances of redmine on Debian squeeze
So, generally:
If you use Debian/Ubuntu go with option #2
Otherwise go with #1
Rolling forward a couple of years, and you might now want to consider a third option of using docker containers for each of your redmine instances.
I've been using https://github.com/sameersbn/docker-redmine.git , and have been quite happy with it except that it doesn't yet support handling of incoming mail for creating and commenting on tickets.

Can I safely run multiple instances of the same Windows Service?

I have a windows service running on a server. It's a 'helper app' for a system we have and it does a very specific task (downloads html files based on the config) with a specific database configuration.
We're now developing a system that's very similar to the existing system (at least on the face of it, where this service has an impact). I need to have a different instance of the service to run the same server with a different database configuration, so it can do its task for the new system, as well as the existing system.
Can somebody tell me if it's going to cause problems if I install a second instance of the same service on the same box?
I intend to install the service from a different directory from where the original is installed.
It turns out I couldn't. I needed to give each instance of the service a unique name. Not a big deal though.
This won't be a problem at all as long as the program itself does not do things in a way that would cause the various instances to conflict - like trying to write to the same files at the same time, or the like. As long as each is configured/coded to keep to itself, it will be fine.

Resources