Possible method for dealing without crons

Post all your tuts or request for tuts here.
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Possible method for dealing without crons

Post by Jackolantern »

I had an idea for this a few minutes ago. Hopefully it could be a viable technique for updating world states without the use of crons.

It is pretty simple and straight forward really. You simply set up certain player actions to poll to see if a change is required. These polls, or "agents of change" (AC) can occur where sensible. While there are more simple methods to deal with this problem, we can use OldRod's problem in another thread about wanting to have a fictional calendar in his game that moved differently from the real calendar (likely faster). We will just say it needs to update every 2 hours. To achieve this, you would need to have a TIMESTAMP field in the table that controls the date (it must be set to display the time as well, if your logic requires it; the calendar in this example would). That way, the last time the item was altered in the database, it would be marked. Then, when a player tries to pull up the calendar, you would need to check that timestamp before displaying it. If it has been over 2 hours since it was last altered, a script runs to update it in the database for everyone. Then if another player loads the calendar and it has not been 2 hours since it was last updated, they simply get the date with no alteration to the database. As long as the timestamp field is in the same table as what you are querying for, there should be no MySQL-connection performance loss when an update is not required. You will be pulling the timestamp out on the same query you would need to make anyway, so all you would have to do is check it in the array. Only if an update to the data is needed would you need to run another query (well, 2 more queries actually, one to update the db, and another to fetch the updated info, but it still shouldn't matter provided you aren't running updates several times a minute).

One other consideration that needs to be taken is that if you are incrementing a value, which may be the case with the calendar (incrementing a date and month for example), you need to take into account that there will likely be times when no players will be on. There needs to be code that runs before the query to update the variable that checks to see if multiple periods have passed without an update.

For example, here is pseudo-code for the calendar solution:

Code: Select all

//Running code to check calendar to display to player.
//gameDate table assumed to only have 1 entry, the in-game date info and timestamp, so no WHERE clause needed.
$query = "SELECT * from gameDate";
$queryResult = mysqli_query($db, $query) or die ("Issue pulling up date. Please try again later.");
$queryArray = mysqli_fetch_assoc($queryResult);

//Check the date of last change (psuedo-code; would need cleaning up)
$timeDifference = current_time() - $queryArray['timestamp'] ;
$hoursSince = $timeDifference / 60 / 60;    //divide first for minutes, then hours
$daysNeeded = $hoursSince / 2;   //find out how many 2 hour periods have occured

//Cast the "days needed" variable to an integer to ensure truncating off any decimal
$daysUpdating = (integer)$daysNeeded;

//Check to see if update required, and do the update and return a fresh date variable from the db to display if needed
if ($daysUpdating >= 1) {
     
     /////Logic to alter any other date fields, such as month or year, based on the $daysUpdate variable goes here
     ////This may include month, year, etc. Do calculations and prepare variables to update 
     ////this info in the below UPDATE query

     //update the date
     $query2 = "UPDATE query to add $daysUpdating to the current date and update anything else";
     mysqli_query($db, $query);
     
     //Get a fresh date array from the db
     $query3 = "SELECT * from date";
     $queryResult3 = mysqli_query($db, $query3) or die ("Could not get new date variable");
     $queryArray3 = mysqli_fetch_assoc($queryResult3);

     //Print the date in calendar format. Will only echo date here:
     echo "Today's game world date is ".$queryArray3['date']."!";

} else {
     //If there was no update needed, display the date with the original, correct date array variable
     echo "Today's game world date is ".$queryArray['date']."!";
}
This is just an alteration of the "On view" crons alternative method. Instead of merely updating database fields relevant for one player, it is using date-checking code so that one player is updating the database field used by everyone without knowing it.
The indelible lord of tl;dr
User avatar
OldRod
Posts: 1320
Joined: Sun Sep 20, 2009 4:26 pm

Re: Possible method for dealing without crons

Post by OldRod »

That's a cool idea Jack, and I had been tinkering with doing just that, but I hadn't had a chance to try it out yet. I may just try your code out :)
User avatar
Torniquet
Posts: 869
Joined: Sun Aug 02, 2009 6:18 am

Re: Possible method for dealing without crons

Post by Torniquet »

n1 jack.

i have never really loked into altering global data via user interactivity. always thought it could lead to some major problems. but hey looks like it mite work.

*big thumbs up to you*
New Site Coming Soon! Stay tuned :D
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Re: Possible method for dealing without crons

Post by Jackolantern »

I thought it may be an issue as well, because, of course, what if the players aren't doing those activities that cause the world to update? However, as long as the functions to check and update the world are tied directly to the activity of the player pulling up the relevant data, I think it should work. If there is no one checking the value, it shouldn't matter if it is out of date :)
The indelible lord of tl;dr
User avatar
hallsofvallhalla
Site Admin
Posts: 12026
Joined: Wed Apr 22, 2009 11:29 pm

Re: Possible method for dealing without crons

Post by hallsofvallhalla »

nice work, This should work really well

unless i am reading to usage wrong you may have a issue with identical activity updates. When you get a few hundred players you may end up with identical updates because you are pulling a global variable.

example, player1 pulls calendar and time has passed and a update proceeds.
player2 pulls same data few miliseconds later and the update also proceeds.
User avatar
OldRod
Posts: 1320
Joined: Sun Sep 20, 2009 4:26 pm

Re: Possible method for dealing without crons

Post by OldRod »

That is the only issue I can see with this method, too. Depending on how you calculate it though, it shouldn't be a problem.

Example: if 2 people both do an update at the same time, and both calculate the date from a fixed beginning point, the answer should be the same (hopefully) :)

I intend to try this out - I've just been swamped with work that past week or so and haven't had a chance.
User avatar
hallsofvallhalla
Site Admin
Posts: 12026
Joined: Wed Apr 22, 2009 11:29 pm

Re: Possible method for dealing without crons

Post by hallsofvallhalla »

as long as you do not make it variable - variable +1 type of code.
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Re: Possible method for dealing without crons

Post by Jackolantern »

Even if you did need variable +1 code, the chance of another check occurring during the 1 or 2 milliseconds it would take to run the update query on a server of less than a couple hundred people would be quite low. If it was a process that the player had to interact with, then the chance would be very high. However, since SQL scripts like this that only deal with one row can usually run in about 1.3ms, we are talking one in a million or higher unless your game has thousands upon thousands of players.

For most situations, such as healing ticks, it wouldn't be a big issue anyway. Players would just get back an extra tick on that once-in-a-blue-moon event. However, if it was crucial that it could absolutely never happen, such as with a calendar date, you could add more logic to double check how long the old value has been there as well as the last time of update before it will attempt the update query.
The indelible lord of tl;dr
User avatar
hallsofvallhalla
Site Admin
Posts: 12026
Joined: Wed Apr 22, 2009 11:29 pm

Re: Possible method for dealing without crons

Post by hallsofvallhalla »

you would be surprised on how slow the mysql can be on the full update. When using ajax you have to set a delay in any windiw.refresh or window.location to keep from stopping your query before it has time.

To be honest I do not know enough about the calculated seconds on a update like you are saying so you might be right. BUT if it can happen it will happen :)
User avatar
Jackolantern
Posts: 10891
Joined: Wed Jul 01, 2009 11:00 pm

Re: Possible method for dealing without crons

Post by Jackolantern »

hallsofvallhalla wrote:you would be surprised on how slow the mysql can be on the full update. When using ajax you have to set a delay in any windiw.refresh or window.location to keep from stopping your query before it has time.

To be honest I do not know enough about the calculated seconds on a update like you are saying so you might be right. BUT if it can happen it will happen :)
If you run queries through the console instead of through PHPMyAdmin, it will tell you how long the query took. If you are adding hundreds of records it may take up to about 0.05 seconds, but most of my low-record queries run in around the 0.001s - 0.004s range. MySQL is an extremely fast db for being free and open source, and query times are basically non-existent until you get up into the thousands of users or thousands of records modified.

EDIT: And again, if it would be disastrous to have it double a tick, you can always add more logic to check it before it updates the global fields while using the same general idea. If you don't have access to crons, I really don't know what your other options are ;)
The indelible lord of tl;dr
Post Reply

Return to “Tutorials”