Last Seen update frequency design problem - asp.net-mvc

I have a DateTime LastSeen property that stores in the database when the user was last seen.
I have 1 way in mind when to update the database is to do it when validating the user during logging in.
Another way is if I'm going to update the database every 20 minutes, where do I put this logic in asp.net mvc? Do I need to set a lastupdate in the cookie and check that? Where would I check this cookie other than in the global.ascx. file?
How do other systems do it?

Personally, I would take a page out of google analytics' book and run this client side. To get there:
a) Setup a Handler/Action/something that takes http requests to handle recording user "seen" activities
b) Setup an ajax call to (a) to record activities at a reasonable interval from the client.
This will let you get to a much better answer to the question "what if bob just opened the site, saw he didn't have any messages and went on browsing [whatever]"

I think as you suggest, update that value when the user logs on would be simplest.
If you model also has CreatedOn, CreatedBy, ModifiedOn, ModifiedBy properties you can also query these values with a join onto the user table to see if they have been active elsewhere in the app but this may not be great in performance as you'll need a join on every table in your database.

Related

Using Ruby on Rails, what is an efficient method of ordering separate users post_id's sequentially?

My domain structure is similar to this:
www.domain.com/:user_id/post/:post_id
i.e. www.domain.com/user1/post/1
I would like it to work where each user's post increments up the user's last :post_id, disregarding the actual ID of the database row, as multiple users posts will be stored there, like so:
www.domain.com/user1/post/1
www.domain.com/user1/post/2
www.domain.com/user2/post/1
www.domain.com/user2/post/2
I understand I will need a "secondary_id" column in the Post database and before committing a post to the database I will need to query the last post of the user to obtain that secondary_id to increment but I'm unsure where this logic would best reside in my app structure and what can I do to simplify/automate the process?
Also, how can I avoid race conditions on the secondary_id if this where implemented in a team environment where users could be submitting posts in between when another user has queried for the last secondary_id to increment and the second user would error out since the other user got to that secondary_id first?

"Archive" a table on rails

long time reader first time poster.
I recently started using ruby on rails so I am still very new to the environment (even though I have completed a few guides) so be gentle please.
What I want to do is create a sort of archive table of another table that the user can access at any time(via a different link on the website).
So for example, if I have the "users" table, I want to be able to archive old users but still give the option for someone to go and view them.
Basically, it will sort of have to delete the user from the initial table, and save his/her info in to the archived_users table.
Thank you for your time.
I figured my comment was more of an answer, so posting it here and adding more info
In this situation you're better off adding some sort if "active" flag to the users table, which you can flip on or off as needed. That way you don't need to worry about dealing with yet another model class, and you can reuse all the same view and controller structures. In your views, you can then simply "hide" any inactive users (and maybe only show inactive folks if the logged in user is an admin...etc).
You also have the freedom to include other meta data such as "deactivated on" (time stamp) for example.
Long story short, if you're concerned about performance, with proper indexing (and partitioning if necessary), you shouldn't really need to create a separate archive table.
The only reason I can think of to do this is if you're dealing with billions upon billions of records, and/or growing by an insane amount (which is probably not your case).
The best way to do this is probably to add a column called deleted on the original Users table. You can then filter out the old users in normal circumstances (preferably using a default scope) but allow them to be seen/queried when needed.
Papertrail might work for you.
It creates a "versions" table and logs create/update/destroy events for any class which includes has_paper_trail. For example:
class User < ActiveRecord::Base
has_paper_trail
end
deleted_users = Papertrail::Version.where(item_type: User, event: "destroy")
deleted_users.last.reify.name # assuming the users table has a 'name' column

How to design a database in rails where all tables can be filtered by a global setting? Default global scope?

I am building a rails app and the data should be reset every "season" but still kept. In other words, the only data retrieved from any table should be for the current season but if you want to access previous seasons, you can.
We basically need to have multiple instances of the entire database, one for each season.
The clients idea was to export the database at the end of the season and save it, then start fresh. The problem with this is that we can't look at all of the data at once.
The only idea I have is to add a season_id column to every model. But in this scenario, every query would need to have where(season_id: CURRENT_SEASON). Should I just make this a default scope for every model?
Is there a good way to do this?
If you want all the data in a single database, then you'll have to filter it, so you're on the right track. This is totally fine, as data is filtered all the time anyway so it's not a big deal. Also, what you're describing sounds very similar to marking data as archived (where anything not in the current season is essentially archived), something that is very commonly done and usually accomplished (I believe) via setting a boolean flag on every record to true or false in order to hide it, or some equivalent method.
You'll probably want a scope or default_scope, where the main downside of a default_scope is that you must use .unscoped in all places where you want to access data outside of the current season, whereas not using a default scope means you must specify the scope on every call. Default scopes can also seem to get applied in funny places from time to time, and in my experience I prefer to always be explicit about the scopes I'm using (i.e. I therefore never use default_scope), but this is more of a personal preference.
In terms of how to design the database you can either add the boolean flag for every record that tells whether or not that data is in the current season, or as you noted you can include a season_id that will be checked against the current season ID and filter it that way. Either way, a scope of some sort would be a good way to do it.
If using a simple boolean, then either at the end of the current season or the start of the new season, you would have to go and mark any current season records as no longer current. This may require a rake task or something similar to make this convenient, but adds a small amount of maintenance.
If using a season_id plus a constant in the code to indicate which season is current (perhaps via a config file) it would be easier to mark things as the current season since no DB updates will be required from season to season.
[Disclaimer: I'm not familiar with Ruby so I'll just comment from the database perspective.]
The problem with this is that we can't look at all of the data at once.
If you need to keep the old versions accessible, then you should keep them in the same database.
Designing "versioned" (or "temporal" or "historized") data model is something of a black art - let me know how your model looks like now and I might have some suggestions how to "version" it. Things can get especially complicated when handling connections between versioned objects.
In the meantime, take a look at this post, for an example of one such model (unrelated to your domain, but hopefully providing some ideas).
Alternatively, you could try using a DBMS-specific mechanism such as Oracle's flashback query, but this is obviously not available to everybody and may not be suitable for keeping the permanent history...

The way to implement User Email Preferences?

I want to implement a feature which lets every user decide the kind of emails he/she will receive. So far, I can only see the user receiving emails when he/she receives a friendship request and when he/she receives a new message. The way I plan to implement this is as follows:
Each User has_one EmailPreference
EmailPreferences table will have 2 columns: Friendship (Boolean) and Message (Boolean).
By default, they will be true. So the User will receive emails for both new messages and new requests received.
The user can go to the Edit action and update the values as per his choice.
I plan on using an if statement which will check if #user.emailpreference.message? or #user.emailpreference.friendship? before the send email method.
I'd like to know if this is the best way to go about it.
A couple considerations - I'd question whether you want to do the has_one or simply add the columns to the user. I also tend to use dates instead of booleans, so you can see when the boolean was set. For naming, consider something other than 'friendship' and 'message'. If it is an attribute on the user, I'd consider something like 'subscribed_to_friendships' and 'subscribed_to_messages'.
The reason I avoid has_one's in general is to make very simple queries and reduce the need for maintenance. It's likely you'll be getting all users that should receive a message and looping through them, I prefer to avoid the joins and keep it simple. I also don't really like how false and null are the same on the child. This will help you avoid deleting/adding preference records, especially if the default is true and you're going to create preferences for most users by default.
I see one issue in the approach is that if tomorrow you have more type as preference , means when somebody joins than also you want to send the email , in that case you have to add one more column. Why do not you normalize it further and use more table to store the Preference type
Id Name
1 Friendship
2 Message
Id User Id Flag
1 1 TRUE
2 1 False
It means user 1 is opted for Friendship but not for Message. Now you can easily add any new preference.
the approach by https://stackoverflow.com/users/177489/swards is for me , the best option because that has_one queries can be a mess later.
add columns to user model and gg!

Identifying a connection ID in Postgres

I have a Postgres database (9) that I am writing a trigger for. I want the trigger to set the modification time, and user id for a record. In Firebird you have a CONNECTIONID that you can use in a trigger, so you could add a value to a table when you connect to the database (this is a desktop application, so connections are persistent for the lifetime of the app), something like this:
UserId | ConnectionId
---------------------
544 | 3775
and then look up in the trigger that connectionid 3775 belongs to userid 544 and use 544 as the user that modified the record.
Is there anything similar I can use in Postgres?
you could use the process id. It can be retrieved with:
pg_backend_pid()
With this pid you can also use the table pg_stat_activity to get more information about the current backend, althouht you already should know everything, since you are using this backend.
Or better. Just create a serial, and retrieve one value from it for each connection:
CREATE SEQUENCE 'connectionids';
And then:
SELECT next_val('connectionids');
in each connection, to retrieve a connection unique id.
One way is to use the custom_variable_classes configuration option. It appears to be designed to allow the configuration of add-on modules, but can also be used to store arbitrary values in the current database session.
Something along the lines of the following needs to be added to postgresql.conf:
custom_variable_classes = 'local'
When you first connect to the database you can store whatever information you require in the custom class, like so:
SET local.userid = 'foobar';
And later in on you can retrieve this value with the current_setting() function:
SELECT current_setting('local.userid');
Adding an entry to a log table might look something like this:
INSERT INTO audit_log VALUES (now(), current_setting('local.userid'), ...)
While it may work for your desktop use case, note that process ID numbers do rollover (32768 is a common upper limit), so using them as a unique key to identify a user can run into problems. If you ever end up with leftover data from a previous session in the table that's tracking user->process mapping, that can collide with newer connections assigned the same process id once it's rolled over. It may be sufficient for your app to just make sure you aggressively clean out old mapping entries, perhaps at startup time given how you've described its operation.
To avoid this problem in general, you need to make a connection key that includes an additional bit of information, such as when the session started:
SELECT procpid,backend_start FROM pg_stat_activity WHERE procpid=pg_backend_pid();
That has to iterate over all of the connections active at the time to compute, so it does add a bit of overhead. It's possible to execute that a bit more efficiently starting in PostgreSQL 8.4:
SELECT procpid,backend_start FROM pg_stat_get_activity(pg_backend_pid());
But that only really matters if you have a large number of connections active at once.
Use current_user if you need the database user (I'm not sure that's what you want by reading your question).

Resources