Question

This is more of a logic question than language question, though the approach might vary depending on the language. In this instance I'm using Actionscript and PHP.

I have a flash graphic that is getting data stored in a mysql database served from a PHP script. This part is working fine. It cycles through database entries every time it is fired.

The graphic is not on a website, but is being used at 5 locations, set to load and run at regular intervals (all 5 locations fire at the same time, or at least within <500ms of each-other). This is real-time info, so time is of the essence, currently the script loads and parses at all 5 locations between 30ms-300ms (depending on the distance from the server)

I was originally having a pagination problem, where each of the 5 locations would pull a different database entry since i was moving to the next entry every time the script runs. I solved this by setting the script to only move to the next entry after a certain amount of time passed, solving the problem.

However, I also need the script to send an email every time it displays a new entry, I only want it to send one email. I've attempted to solve this by adding a "has been emailed" boolean to the database. But, since all the scripts run at the same time, this rarely works (it does sometimes). Most of the time I get 5 emails sent. The timeliness of sending this email doesn't have to be as fast as the graphic gets info from the script, 5-10 second delay is fine.

I've been trying to come up with a solution for this. Currently I'm thinking of spawning a python script through PHP, that has a random delay (between 2 and 5 seconds) hopefully alleviating the problem. However, I'm not quite sure how to run exec() command from php without the script waiting for the command to finish. Or, is there a better way to accomplish this?

UPDATE: here is my current logic (relevant code only):

//get the top "unread" information from the database

$query="SELECT * FROM database WHERE Read = '0' ORDER BY Entry ASC LIMIT 1";


   //DATA 
    $emailed = $row["emailed"];
    $Entry = $row["databaseEntryID"];


if($emailed == 0)

{

**CODE TO SEND EMAIL**

$EmailSent="UPDATE database SET emailed = '1' WHERE databaseEntryID = '$Entry'";
$mysqli->query($EmailSent);
}

Thanks!

Was it helpful?

Solution

You need to use some kind of locking. E.g. database locking

function send_email_sync($message)
{
    sql_query("UPDATE email_table SET email_sent=1 WHERE email_sent=0");
    $result = FALSE;
    if(number_of_affacted_rows() == 1) {
        send_email_now($message);
        $result = TRUE;
    }
    return $result;
}

The functions sql_query and number_of_affected_rows need to be adapted to your particular database.

Old answer:

Use file-based locking: (only works if the script only runs on a single server)

function send_email_sync($message)
{
    $fd = fopen(__FILE__, "r");
    if(!$fd) {
        die("something bad happened in ".__FILE__.":".__LINE__);
    }
    $result = FALSE;
    if(flock($fd, LOCK_EX | LOCK_NB)) {
        if(!email_has_already_been_sent()) {
            actually_send_email($message);
            mark_email_as_sent();
            $result = TRUE; //email has been sent
        }
        flock($fd, LOCK_UN);    
    }
    fclose($fd);
    return $result;
}

OTHER TIPS

You will need to lock the row in your database by using a transaction.

psuedo code:

Start transaction
select row .. for update
update row
commit


if (mysqli_affected_rows ( $connection )) >1
    send_email();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top