Logic Behind An Upvote Button?

built

//
BuSo Pro
Boot Camp
Joined
Jan 23, 2015
Messages
1,676
Likes
1,441
Degree
4
I'm trying to add voting to my website but I'm a little confused about how the logic is structured.

How do I run
Code:
IncrementVote()
on the server from the client?

Is that even the correct approach?
 
You'll need an AJAX call, which is a JavaScript function that sends data to the server where it can be processed, and the server can then return some response, all without the user having to reload the browser. So it would go something like:

1. User clicks upvote button
2. Fire AJAX call to server
3. Server increments vote count in the database and sends success message back, otherwise returns an error
4. The AJAX call 'success' handler gets and checks the response and adds a thank you message to the screen, increments the page's vote counter, re-sorts the rankings, etc.
 
One thing to consider is, depending on the traffic levels, you'll be pinging the database quite a bit. Not only reading but writing and then reading again.

That's going to mean doing something to throttle the amount you query/write the database unless you want to eventually have exorbitant server fees (of course, depending on the traffic again).

Hitting the database for every user response would be silly when you could instead cache the responses and deliver a fake incrementing in the time being. You could cache all the votes in some kind of text file and then read and write to the database maybe once every second, minute, 15 minutes, hour, etc. Depending on your traffic. Reading and writing JSON to a text file is going to be less intensive than going raw to the database over and over.

I'm just tossing this out as food for thought. It won't be an issue and not something you should worry about until your project is getting a lot of traction.
 
You'll need an AJAX call, which is a JavaScript function that sends data to the server where it can be processed, and the server can then return some response, all without the user having to reload the browser. So it would go something like:

1. User clicks upvote button
2. Fire AJAX call to server
3. Server increments vote count in the database and sends success message back, otherwise returns an error
4. The AJAX call 'success' handler gets and checks the response and adds a thank you message to the screen, increments the page's vote counter, re-sorts the rankings, etc.
Ah that makes sense, I'm gonna have to do some research on AJAX, thanks for the simple explanation!

One thing to consider is, depending on the traffic levels, you'll be pinging the database quite a bit. Not only reading but writing and then reading again.

That's going to mean doing something to throttle the amount you query/write the database unless you want to eventually have exorbitant server fees (of course, depending on the traffic again).

Hitting the database for every user response would be silly when you could instead cache the responses and deliver a fake incrementing in the time being. You could cache all the votes in some kind of text file and then read and write to the database maybe once every second, minute, 15 minutes, hour, etc. Depending on your traffic. Reading and writing JSON to a text file is going to be less intensive than going raw to the database over and over.

I'm just tossing this out as food for thought. It won't be an issue and not something you should worry about until your project is getting a lot of traction.
I didn't actually think of that scenario so thanks for bringing it up. I honestly don't know much about caching so I'll need to research this too.
 
Writing to a MYSQL database and writing a textfile does the same end result, writing to the harddrive.

If you REALLY want to cache and write once per minute the end result use an in-memory database like REDIS, that way you don't write to the harddrive. You'll just increment the vote count in the hash:

"HINCRBY VOTE_ABC first_option 1"

or

"HINCRBY VOTE_ABC second_option 1"

Then setup a cronjob to empty out the REDIS and write to MYSQL. Since REDIS is completely IN-RAM, it's about 10,000x faster than writing to the harddrive with a textfile or MYSQL.

BUT guys, you literally do not need to do this unless your MYSQL database is on some low-power server, I'm talking about even a $5 a month Linode (1 Core, 1GB of RAM) should be able to take the traffic hit to this simple setup without needing this extra step.

If CNN, FoxNews, and MSNBC combined sent you their traffic for your voting system you still wouldn't need to do the above situation with caching. Your HTTP server (apache2 or NGINX) would bottleneck before any of this happens, and the only thing that will happen is the user's experience will seem slow.

In that scenario instead of using AJAX, use a WebWorker so users won't experience any lag due to javascript. I talk a bit about WebWorkers here, later on in that thread there is a Kirby animation that I use to illustrate the WebWorker versus Ajax. BUT again that's overkill, simple Ajax will work for your scenario IMO.

The writing to MYSQL isn't the problem. MYSQL is written in C. Perl is written in C. PHP is written in C. Redis is written in C. There is a reason.

PHP/Perl writing to MYSQL can do about 45 to 75 writes per second.
C++ can write 1,000 writes per second.
C can write 10,000 writes per second.

Doing the same type of talking to Redis, I got perl to do 2,000,000+ "writes" per second - afterwards send that data to MYSQL once a minute.

ALL on the $5 Linode server. The reason I know is I've done these benchmarks to test out when Redis is needed and not. I talk about C, MYSQL, and Redis situation a couple of times in my SAAS journal, more so here.

If you write bad code then you'll have "caching" problems and it may seem like it's the MYSQL database that's the problem - it's not, it's your code or coding language.

But again even if you have 100,000 people a minute on your server, this voting system is never going to buckle. Your HTTP server is going to think it's getting DDOSed and fail long before you need this caching setup.

When you need a caching scenario is when you are sending or storing chunks of data, like 100kb and above back and forth and users might be on mobile. "vote=2" is 7 bytes. The header information and cookies are bigger in size than this upvoting scenario. Even the response will be a lot bigger.

Don't over-engineer something simple for an "end of the world" scenario that likely to never happen, otherwise you're code will bloat quickly.

Once things start "feeling sluggish" upgrade to a $10 server and then tune your MYSQL. That's it. Even using Innodb versus MYISAM will improve your speed since Innodb doesn't lock the whole table when writing or reading, just the row.

However if you are on some 16 core, 32GB RAM, 2TB server only your coding will be the problem (and whether you tuned your MYSQL db or not).
 
Writing to a MYSQL database and writing a textfile does the same end result, writing to the harddrive.

If you REALLY want to cache and write once per minute the end result use an in-memory database like REDIS, that way you don't write to the harddrive. You'll just increment the vote count in the hash:

"HINCRBY VOTE_ABC first_option 1"

or

"HINCRBY VOTE_ABC second_option 1"

Then setup a cronjob to empty out the REDIS and write to MYSQL. Since REDIS is completely IN-RAM, it's about 10,000x faster than writing to the harddrive with a textfile or MYSQL.

BUT guys, you literally do not need to do this unless your MYSQL database is on some low-power server, I'm talking about even a $5 a month Linode (1 Core, 1GB of RAM) should be able to take the traffic hit to this simple setup without needing this extra step.

If CNN, FoxNews, and MSNBC combined sent you their traffic for your voting system you still wouldn't need to do the above situation with caching. Your HTTP server (apache2 or NGINX) would bottleneck before any of this happens, and the only thing that will happen is the user's experience will seem slow.

In that scenario instead of using AJAX, use a WebWorker so users won't experience any lag due to javascript. I talk a bit about WebWorkers here, later on in that thread there is a Kirby animation that I use to illustrate the WebWorker versus Ajax. BUT again that's overkill, simple Ajax will work for your scenario IMO.

The writing to MYSQL isn't the problem. MYSQL is written in C. Perl is written in C. PHP is written in C. Redis is written in C. There is a reason.

PHP/Perl writing to MYSQL can do about 45 to 75 writes per second.
C++ can write 1,000 writes per second.
C can write 10,000 writes per second.

Doing the same type of talking to Redis, I got perl to do 2,000,000+ "writes" per second - afterwards send that data to MYSQL once a minute.

ALL on the $5 Linode server. The reason I know is I've done these benchmarks to test out when Redis is needed and not. I talk about C, MYSQL, and Redis situation a couple of times in my SAAS journal, more so here.

If you write bad code then you'll have "caching" problems and it may seem like it's the MYSQL database that's the problem - it's not, it's your code or coding language.

But again even if you have 100,000 people a minute on your server, this voting system is never going to buckle. Your HTTP server is going to think it's getting DDOSed and fail long before you need this caching setup.

When you need a caching scenario is when you are sending or storing chunks of data, like 100kb and above back and forth and users might be on mobile. "vote=2" is 7 bytes. The header information and cookies are bigger in size than this upvoting scenario. Even the response will be a lot bigger.

Don't over-engineer something simple for an "end of the world" scenario that likely to never happen, otherwise you're code will bloat quickly.

Once things start "feeling sluggish" upgrade to a $10 server and then tune your MYSQL. That's it. Even using Innodb versus MYISAM will improve your speed since Innodb doesn't lock the whole table when writing or reading, just the row.

However if you are on some 16 core, 32GB RAM, 2TB server only your coding will be the problem (and whether you tuned your MYSQL db or not).
Thanks for the advice. I will be using a $10 droplet from DigitalOcean to start. I'm currently using Asp.net core for the backend with MySQL. My blog portion is hosted with Wordpress on another droplet.

---

Speaking of resources, what is your opinion on Blazor server? It uses a SignalR connection. Is this less efficient than WebWorkers/AJAX? Or are these similar?

Code:
https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-5.0

Edit: Found some performance info for those wondering

In 2019, the ASP.NET Core team did some testing to establish the performance levels of Blazor Server apps. They setup an application in Azure and tested it on different powered virtual machines, checking the number of active users the application could support. Here are the results.

Standard D1 v2 Instance (1vCPU & 3.5GB Memory). Over 5000 concurrent users
Standard D3 v2 Instance (4vCPU & 14GB Memory). Over 20,000 concurrent users
 
Last edited:
What's the best way to do this in Wordpress?

Regarding what @Ryuzaki said, you could use something like Zapier perhaps to count in a Google Sheet and then import with WP All Import, but it would be overkill it seems according to @CCarter.

Does anyone know of a guide to do this in Wordpress?
 
What's the best way to do this in Wordpress?

Regarding what @Ryuzaki said, you could use something like Zapier perhaps to count in a Google Sheet and then import with WP All Import, but it would be overkill it seems according to @CCarter.

Does anyone know of a guide to do this in Wordpress?
This guide explains how to set up AJAX calls in WP and even uses the "vote counter" idea as the demo example (https://www.smashingmagazine.com/2011/10/how-to-use-ajax-in-wordpress/).

In this case, they just save the vote count as some custom post meta. As mentioned above, unless you need to account for a huge amount of traffic, I don't think you have to worry about performance using the default WP database writing functions from that example.
 
Back