tomwalder / php-gds

Google Cloud Datastore Library for PHP
Apache License 2.0
164 stars 44 forks source link

Add utility class/method for transactional counter++ #18

Open tomwalder opened 9 years ago

tomwalder commented 9 years ago

Make it easier for people to use transactions.

Few options for syntax, which I will work on - perhaps...

$obj_thing->incrementInTransaction('count', 1);

or maybe

Utils::adjust($obj_thing, 'count', 1);

...insert more choices here!

tomwalder commented 9 years ago

Whilst not concluded, having now added the Contention exceptions, this should be pretty straight forward!

emilorol commented 8 years ago

Hi Tom,

Can you elaborate on this one? this might be useful for paginations.

Thank you.

tomwalder commented 8 years ago

The idea is that sometimes we need atomic incrementing counters.

Maybe counting the number of posts to a forum thread.

Let's say we have a count of 10.

If we have 2 concurrent posts, we want to ensure that each one results in an increment, rather than both threads incrementing from 10 to 11.

This can be done with transactions.

This issue is here as a reminder for me to provide a utility class with all the transaction and automated retry goodness included.

emilorol commented 8 years ago

Hi Tom,

Meanwhile you can provide some code this is what I am using to count all "post" tagged with the same "word". The logic was to add an integer field that will hold the count and it will increment it or decrement it depending on the operation.

  /**
   * Alter the entity counter
   *
   * @param $entity_id
   * @param $op | plus or minus
   */
  public function alterCount($entity_id, $op) {
    $entity = '';
    $store = $this->getStore();
    $entity = $store->fetchById($entity_id);
    $counter = $entity->counter;

    if ($op == 'plus') {
      $counter++;
    }
    if ($op == 'minus') {
      $counter--;
    }

    $entity->counter = $counter;
    $store->upsert($entity);
  }

Now when adding a new "post" I increment the count:

      $this->post->writeData($data);

      // Update tag count
      $this->tag->alterCount($data['tag'], 'plus');

When deleting a "post" I reduce the count:

      $this->post->deleteEntity($args['id']);

      // Update tag count
      $this->tag->alterCount($data['tag'], 'minus');

Now the question is when I load the entity tag, I will know it is in use by 100 posts, if I want to paginate thru those posts 10 post at the time, how will I do that?

I know from your documentation, I can do something like this:

$store->query('SELECT * FROM Posts');
while($posts = $store->fetchPage(10)) {
    echo "Page contains ", count($posts), " records", PHP_EOL;
}

How do I get the next 10?

How do I set the offset, so that I can get something similar to LIMIT 80,10 ?

emilorol commented 8 years ago

I figure it out. Once again, thank you.

$offset = (--$page * POST_LIMIT);
$posts = $store->fetchPage(10, $offset);
phpso10 commented 8 years ago

Hi Emilorol -- I need some help. My input parameters will be startindex, endindex (like 0,10 or 11,20 or 21,30 and so on). so now for this to work with the query, I have the following php code.

`$obj_schema_2 = new GDS\Schema('inbox'); $obj_gateway_ns_2 = new GDS\Gateway\ProtoBuf(null, 'bkdatastore'); $obj_store_ns_2 = new \GDS\Store($obj_schema_2, $obj_gateway_ns_2); $obj_store_ns_2->query("SELECT * FROM inbox");

$offset ==== it is not working when I pass a offset value here------==== while ($arr_page = $obj_store_ns_2->fetchPage(10,$offset)) { foreach($arr_page as $obj_ch) { echo $obj_ch->inboxid; }`

This is printing (If I just pass the value as 10 without offset) all the records and not just 10. If I pass the offset, then it just doesn't work at all. but I want to display the first 10 records and then when it is passed as 11,20, it should display only from 11-20 records. how did you solve? Please help me out and thank you for your time.

emilorol commented 8 years ago

@phpso10

Try it like this:

$results = $obj_store_ns_2->query("SELECT * FROM inbox");

if (!is_null($results))
 {
      $page_results = $results->fetchPage(10, $offset);
      foreach ($page_results as $page_result)
      {
        echo $page_result->inboxid;
      }
}

Let me know if it works.

phpso10 commented 8 years ago

Thank you so much.... you saved me :) Your services are just awesome. Please keep doing. -Venkat

On Tue, Jun 28, 2016 at 7:22 AM, Emil Orol notifications@github.com wrote:

@phpso10 https://github.com/phpso10

Try it like this:

$results = $obj_store_ns_2->query("SELECT * FROM inbox");if (!is_null($results)) { $page_results = $results->fetchPage(10, $offset); foreach ($page_results as $page_result) { echo $page_result->inboxid; }}

Let me know if it works.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/tomwalder/php-gds/issues/18#issuecomment-229064240, or mute the thread https://github.com/notifications/unsubscribe/ATPGhSzH-q3rZMjQXEJknVmSCfAVOBa4ks5qQS4OgaJpZM4Dj9wt .

phpso10 commented 8 years ago

@emilorol One more question, your query/syntax woks fine if the $offset is less than 1000, but after that it doesn't return any records.. (I have a resultset > 1000) how do I modify your query ?

please help! Thanks a ton!

phpso10 commented 8 years ago

Here is the code -- I am using, basically I get the input parameter as offset and itemsperpage=100 records per paging. if I have 998 as $offset it works fine, but if get as 1001, then it fails. how do I get around or modify my query? $items_per_page=100; $offset=998; while($arr_page = $results->fetchPage($items_per_page,$offset)) {
foreach ($arr_page as $obj_ch) { $recordsperpage= $recordsperpage+1; $response[] = array( "recordNumber"=>$recordsperpage, "channeltitle"=>$obj_ch->title ); } break; }

emilorol commented 8 years ago

Hmmm, maybe we should get Tom involved because I don't know if that is a library issue or a datastore issue.

Have you try using the JSON gateway?

phpso10 commented 8 years ago

for some reason, if I do the following using JSON, it doesn't give me any error and it doesn't return any records: here is what I did.

//$obj_client = GDS\Gateway\GoogleAPIClient::createClientFromJson('/path/to/your/service.json');

$obj_client = GDS\Gateway\GoogleAPIClient::createGoogleClient(GDS_APP_NAME, 'gds-datastore@bottlekast-1001.iam.gserviceaccount.com', GDS_KEY_FILE_PATH);

so I replaced the 2 line of code with JSON (JSON is correct though) but nothing works and no error.

-V

On Mon, Jul 25, 2016 at 7:33 AM, Emil Orol notifications@github.com wrote:

Hmmm, maybe we should get Tom involved because I don't know if that is a library issue or a datastore issue.

Have you try using the JSON gateway?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/tomwalder/php-gds/issues/18#issuecomment-234970837, or mute the thread https://github.com/notifications/unsubscribe-auth/ATPGhVb6gXnEo6LikXi8xcvR8MWyRgXZks5qZMlXgaJpZM4Dj9wt .

phpso10 commented 8 years ago

Is there any php code that uses Query/FetchPage using Cursors that I can use ? I think thats what I am missing to work around with > 1000 records.

On Mon, Jul 25, 2016 at 8:50 AM, Venkat yvenkat@gmail.com wrote:

for some reason, if I do the following using JSON, it doesn't give me any error and it doesn't return any records: here is what I did.

//$obj_client = GDS\Gateway\GoogleAPIClient::createClientFromJson('/path/to/your/service.json');

$obj_client = GDS\Gateway\GoogleAPIClient::createGoogleClient(GDS_APP_NAME, ' gds-datastore@bottlekast-1001.iam.gserviceaccount.com', GDS_KEY_FILE_PATH);

so I replaced the 2 line of code with JSON (JSON is correct though) but nothing works and no error.

-V

On Mon, Jul 25, 2016 at 7:33 AM, Emil Orol notifications@github.com wrote:

Hmmm, maybe we should get Tom involved because I don't know if that is a library issue or a datastore issue.

Have you try using the JSON gateway?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/tomwalder/php-gds/issues/18#issuecomment-234970837, or mute the thread https://github.com/notifications/unsubscribe-auth/ATPGhVb6gXnEo6LikXi8xcvR8MWyRgXZks5qZMlXgaJpZM4Dj9wt .

emilorol commented 8 years ago

Let's continue this chat in #126