Reputation: 67
My website is a community; we have forums and user profiles, and everyone has what are called "merits" which are sort of like the "Reputation" here on StackOverflow. I have a code which runs on a timer that I made. Two scripts run off of this timer; one script runs once per day (which works flawlessly), and the other one runs once per week.
The timer, itself, works fine, but when it comes time to run the weekly code, a couple of really strange things happen: 1) The weekly code runs perfectly the first time, but for some reason, the entire code gets run a second time, and some logging errors occur. 2) When this program runs the second time, it forgets the last time everyone has logged in (the system is supposed to reduce a user's merit status by one if they have been inactive for two consecutive weeks), therefore reducing everyone's merits no matter how active they've been.
I've done my homework, and I thought it was an error with my browser (Firefox loads every page twice, depending on what plugins you have), but this isn't that; every user has a merit log, which records each and every transaction affecting their merit status. Everyone has two transactions by the system, and the second one is exactly one second after the first. Everyone has the same two timestamps. What this means, is that the code runs through, gives everyone what they had coming, and then starts over from the beginning, exactly one second later. This time, however, it gives everyone a Demerit (a subtraction from their merits), unconditionally.
None of this should happen because the first thing my weekly timer does is check to see if it's the right day to do it, and the second thing it does (if it is the right day) is update the timer to next week, so it won't run twice in a single day.
Here it is:
<?php
mysql_connect("connect","username","password");
mysql_select_db("seriamus");
$feduby = mysql_query("SELECT day,week FROM timer WHERE name='timer'");
$timer = mysql_fetch_array($feduby);
//Daily Timer
if($timer[0]==date("M j, Y"))
{
$tomorrow = strtotime("+1 day");
mysql_query("UPDATE timer SET day='" . date('M j, Y', $tomorrow) . "' WHERE name='timer'");
mysql_connect("connect","username","password") or die(mysql_error());
mysql_select_db("agluserdatabase");
$getsuspendinfo = mysql_query("SELECT gamertag,rank,sdate,srank FROM users");
while($suspo = mysql_fetch_array($getsuspendinfo))
{
if($suspo[1]=="Suspended")
{
if($suspo[2]==date("M j, Y"))
{
mysql_query("UPDATE users SET rank='" . $suspo[3] . "', srank='', sdate='' WHERE gamertag='" . $suspo[0] . "'");
}
}
}
}
//Weekly Timer
if($timer[1]==date("M j, Y"))
{
$inaweek = strtotime("+7 days");
mysql_query("UPDATE timer SET week='" . date('M j, Y', $inaweek) . "' WHERE name='timer'");
mysql_connect("connect","username","password") or die(mysql_error());
mysql_select_db("agluserdatabase");
$getmeritinfo = mysql_query("SELECT merits,logins,lastseen,demerit,gamertag,rank,userid FROM users");
while($meritinfo = mysql_fetch_array($getmeritinfo))
{
if($meritinfo[3]==0)
{
if($meritinfo[1]>=3)
{
if($meritinfo[5]!="Suspended"&&$meritinfo[5]!="Banned")
{
$newmerits = $meritinfo[0] + 1;
mysql_query("UPDATE users SET merits='" . $newmerits . "' WHERE gamertag='" . $meritinfo[4] . "'");
mysql_query("INSERT INTO meritlog" . $meritinfo[6] . " VALUES ('System', 'Merit', 1, 'Active for a week without getting a demerit', '" . date('M j, Y g:i:s') . "')");
}
}
else if ($meritinfo[1]==0)
{
$two_weeks_ago = strtotime('-14 days', strtotime(date("M j, Y")));
$last_seen = strtotime($meritinfo[2], strtotime(date("M j, Y")));
if($last_seen <= $two_weeks_ago)
{
if($meritinfo[5]!="Suspended"&&$meritinfo[5]!="Banned")
{
$newmerits = $meritinfo[0] - 1;
mysql_query("UPDATE users SET merits='" . $newmerits . "' WHERE gamertag='" . $meritinfo[4] . "'");
mysql_query("INSERT INTO meritlog" . $meritinfo[6] . " VALUES('System', 'Demerit', 1, '2+ weeks of inactivity', '" . date('M j, Y g:i:s') . "')");
if($newmerits <= -10)
{
mysql_query("UPDATE users SET merits = 0 WHERE gamertag = '" . $meritinfo[4] . "'");
mysql_query("UPDATE users SET lastpromotion = '" . date('M j, Y') . "' WHERE gamertag = '" . $meritinfo[4] . "'");
if($meritinfo[5]=="Praetorian")
{
mysql_query("UPDATE users SET rank = 'Centurion' WHERE gamertag = '" . $meritinfo[4] . "'");
}
else if($meritinfo[5]=="Centurion")
{
mysql_query("UPDATE users SET rank = 'Triarius' WHERE gamertag = '" . $meritinfo[4] . "'");
}
else if($meritinfo[5]=="Triarius")
{
mysql_query("UPDATE users SET rank = 'Decanus' WHERE gamertag = '" . $meritinfo[4] . "'");
}
else if($meritinfo[5]=="Decanus")
{
mysql_query("UPDATE users SET rank = 'Prime Legionary' WHERE gamertag = '" . $meritinfo[4] . "'");
}
else if($meritinfo[5]=="Prime Legionary")
{
mysql_query("UPDATE users SET rank = 'Legionary' WHERE gamertag = '" . $meritinfo[4] . "'");
}
else if($meritinfo[5]=="Legionary")
{
mysql_query("UPDATE users SET rank = 'Banned' WHERE gamertag = '" . $meritinfo[4] . "'");
}
}
}
}
}
}
mysql_query("UPDATE users SET logins='0', demerit='0' WHERE gamertag='" . $meritinfo[4] . "'");
}
}
?>
Within this code, there's also some things relating to the users' rank, or how many demerits they've been given that week, or whether they've been suspended or banned, etc. They shouldn't be important, but I included them anyways so you can get the entire code.
Let me know if you need me to elaborate on what the whole code is specifically set up to do.
Thank you, in advance, for taking the time to read all this and (hopefully) help me out with it! Any help at all would be appreciated, even if it's some efficiency method that's completely irrelevant to the problem -- any help at all would be great! :D
Upvotes: 3
Views: 1507
Reputation: 603
We suffered this issue because we are using a jquery widget that had a template element like this:
<div><img src="#{icon}" /></div>
where the #{icon} was being replaced via the widget function with 'path/to/icon.png'. However, on page load the "#" was causing the script to be loaded again by the browser, and session variables were getting borked. The fix was to edit the template to:
<div>#{icon}</div>
where the #{icon} would be replaced with '' instead.
This may not be your answer, but when we were looking for one, your question came up and it would have been handy to see one like this.
Upvotes: 0
Reputation: 956
I think your having an issue because it loads twice.
First load
Selects table Updates daily Starts processing
Then second load happens.
Selects table Skips daily Updates weekly Starts processing
Then the first load again.
Updates weekly (again, because it doesn't check it) Starts processing
I'd recommend doing 'LOCK TABLES timer WRITE' then an 'UNLOCK TABLES' at the end. Also, you would need to clean up your database accesses with link identifiers, I.e.
$timer = mysql_connect(); mysql_query(..., $timer);
Also, push the code to a cron.php or something similar, regular checks like this are not a good idea on main pages. Another option would be to generate random number and only check 1% of time. But best bet is cron, even if you just set it up as a you load the page from your computer once a day.
Upvotes: 1