Hello Guys,

I have question how the concurrency is handled in the services? Is there a way to make a particular method non-reentrant?

Regards,
Ivan

Comments

nekobul’s picture

Category: support » feature

None to comment?

I have come up with solution used in other projects. I used temporary variable, using variable_set / variable_get / variable_del to maintain concurrency. It would be great to integrate this idea in the services core.

marcingy’s picture

Version: 5.x-1.x-dev » 6.x-1.x-dev
Status: Active » Postponed (maintainer needs more info)

Please submit a patch for your use case so as we can review and add to services core.

nekobul’s picture

Version: 6.x-1.x-dev » 5.x-0.92
Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new2.82 KB

Marc,

Find attached patch and additional file for managing services semaphores.

nekobul’s picture

StatusFileSize
new2.82 KB

Marc,

Find attached patch and additional file for managing services semaphores. The code includes:

1. New service method attribute (#reentrant) for specifying if particular method is re-entrant or not re-entrant.
2. Services administration for manually releasing hanging semaphores.
3. Setting for specifying time frame for non re-entrant method to complete execution before it fails with service error that the service is busy.

marcingy’s picture

Version: 5.x-0.92 » 6.x-1.x-dev

Note this will only be added to drupal 6 as drupal 5 is feature frozen and please provide the code as a patch file.

marcingy’s picture

Status: Needs review » Needs work
nekobul’s picture

Marc,

We currently use 5.x in our projects, so unfortunately I will not be able to send version for 6.x. If someone else is interested to make the changes in the newer branch, he is more than welcome. The additions are pretty straightforward.

Hugo Wetterberg’s picture

Ivan and Marc,
I don't see any obvious reasons for adding generic semaphore support on the method granularity level. That is not to say that I don't see the point of semaphores and other concurrency strategies in general, but I think that the methods that use semaphores should take care of that on their own. The need for semaphores seems too rare to motivate it's inclusion in services, in most cases the method granularity is probably insufficient or wrong anyway.

What would make sense, to me at least, is to make a more general semaphore module. Complete with timeouts and all the other goodies. It would then fall to the service that is in need of semaphores to utilize this semaphore module as it sees fit, using whatever granularity level it wishes.

Cheers
/Hugo

nekobul’s picture

Hugo,

The first time we had to implement services methods of our own, we were in need of concurrency control. This is not representative extract, but still the need is there. The issue at hand is that we don't have semaphore module readily available. The proposed solution is not perfect, but in the meantime it is the best ready for use NOW.

marcingy’s picture

Status: Needs work » Closed (won't fix)

Hugo

Thanks for your feedback andgiven your arguments I'm going to set this as won't fix simply because it isn't a service specific matter.

Marc

Hugo Wetterberg’s picture

Ivan,
First of all I want to say that I don't disapprove of the semaphore functionality, nor do I have any serious reservations about your implementation. I think that it's great that you both have idéas and the talent to back them up with actual code.

But as it only is edge-cases that have the need for this functionality, and to repeat my previous argument: for most of those edge cases semaphores that use method-level granularity will not be satisfactory. What I propose, a separate semaphore module, is just as much a solution that is ready for use now. It only requires you to create it. Just make sure that you don't use variables for semaphores, but create a dedicated table instead. This is because all variables are loaded upon every requests, and setting variables all the time will prevent efficient caching of variables. In other words it will cause a site-global memory and performance hit.

What i envision is a module "semaphore" that essentially provides the following functions:

  /**
   * Function used to acquire a semaphore to lock common resources.
   *
   * @param string $name 
   * @return bool
   *  Returns TRUE if the semaphore was acquired, otherwise FALSE is returned.
   */
  function semaphore_acquire($name) {
    //...
  }

  /**
   * Function used to release a semaphore.
   *
   * @param string $name 
   * @return void
   */
  function semaphore_release($name) {
    //...
  }

Your service callback then just has to use this API.

  function _your_service_callback($arg1) {
    if (!semaphore_acquire('_your_service_callback')) {
      return services_error(t("'!method' service is busy. Please try again in a moment.", array('!method' => '_your_service_callback')));
    }

    //...

    semaphore_release('_your_service_callback');
    return $result;
  }

This way of doing it could just as easily cover the following scenario:

  function _your_service_callback_2($nid) {
    $semaphore = '_your_service_callback_2_' . $nid;
    if (!semaphore_acquire($semaphore)) {
      return services_error(t("The node !node is busy. Please try again in a moment.", array('!node' => $nid)));
    }

    //...

    semaphore_release($semaphore);
    return $result;
  }

...thus solving our granularity problem in one fell swoop.

Cheers,
/Hugo

nekobul’s picture

Hugo,

What I meant by now is that the proposed functionality is already implemented and ready for integration. However I agree 100% with your argument. If I get the chance, I will try to put some work toward such semaphore module.

Hugo Wetterberg’s picture

Great! Looking at this has given me a lot of idéas re. services extensibility. There is a lot that needs to be done in this area. We'll need some more hook_alters to allow other modules that the active auth-module to alter the method definitions. I also think that we would need "#before call" and "#after call" attributes for methods, similar in function to the form elements #after_build. That would open up for augmentation by third party modules and help keeping services focused on core functionality.

Just holla when you've started on the semaphore module, then we'll see where we can take it.

/Hugo