-
Notifications
You must be signed in to change notification settings - Fork 952
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How do I implement Memory Storage #469
Comments
Hey there, This is useful for setting up clients quickly and for running tests - you can load clients/access tokens from YAML or static PHP into the You will want to use |
That is fine I understand now. I Copy the PDO Storage class and made a new one PDOMemCache, this class use Memcache for caching in memory (MemCache is super fast) so when user is asking for a resource in the getAccessToken method I run the query against the database only first time if I have not in memcache, I save the result for future use, let say you got a memcache 10 min its ok. This way I avoid the overhead of making a sql query to the database each time, think about an api writted for an phone app and that a phone app calls many time to the api with the same token, this multiplies by the numbers of user using the app it a huge number, I am implementing an api that will be used widely by android, iphone, windows phone it must by really fast. I do some apache benchmark for some service I provide and time is really important, for example This is what I did: /* OAuth2\Storage\AccessTokenInterface */
public function getAccessToken($access_token)
{
$stmt = $this->db->prepare(sprintf('SELECT * from %s where access_token = :access_token', $this->config['access_token_table']));
$cacheKey = 'query-'.md5(serialize(array($stmt->queryString, compact('access_token'))));
# Try and get from memory
$checkCache = $this->memcache->get($cacheKey);
# We have some data
if(!empty($checkCache)) {
return $checkCache;
}else{
$token = $stmt->execute(compact('access_token'));
if ($token = $stmt->fetch()) {
// convert date string back to timestamp
$token['expires'] = strtotime($token['expires']);
$this->memcache->set($cacheKey, $token, 0, 600);
}
}
return $token;
} |
This is a great idea! What you could actually do is make a memcache class that accepts any other storage class as its first argument, and calls that class if the cache key doesn't exist. It would look something like this: class Memcache implements AccessTokenInterface
{
protected $storage;
protected $memcache;
public function __construct(AccessTokenInterface $storage, $memcache)
{
$this->storage = $storage;
$this->memcache = $memcache;
}
public function getAccessToken($access_token)
{
$cacheKey = 'storage-'.$access_token;
# Try and get from memory
$accessToken = $this->memcache->get($cacheKey);
# We have some data
if(!empty($accessToken)) {
return $accessToken;
}
$accessToken = $this->storage->getAccessToken('access_token');
$this->memcache->set($cacheKey, $accessToken, 0, 600);
return $token;
}
} |
WooooW that would be really helpfull can this be added to the Main repo, I think this method will always have to update the token in the passed $storage and also in mem_cache ?.. What do you think? I can implement it and share some benchmark showing it benefits, what I must do to get a pull request approved by you? Regards. |
I would love that very much! Please do so. |
I have done it, I need your help with the test, I run phpunit and get the error: The data provider specified for OAuth2\Storage\AccessTokenTest::testSetAccessToken is invalid. For every test, what I messed up, is something that needs to be configured before running test?, Is there any documentation on running tests somewhere?. Regards. |
Hmm... I've written the tests so it should skip any tests that you don't have drivers for. Can you run the tests with |
Also, if you post your branch on github I can pull it down and run the tests, as my machine is set up. To run ALL the tests, you need the following:
But as i said, the library should skip those tests if they are not configured. |
I was wondering what the progress was of this? It would definitely be a useful addition |
I don't think @sandinosaso ever submitted a pull request... but feel free to submit one as well @pjebs |
I never did but I can if you let me, the code is really simple as bshaffer suggested I implemented passing a valid storage, so I am using PDO storage with a mysql database and usign Memcache to faster retrieve access tokens namespace OAuth2\Storage;
use Memcache;
class MemCacheToken implements AccessTokenInterface
{
protected $storage;
protected $memcache;
public function __construct(AccessTokenInterface $storage, $config=array())
{
$this->storage = $storage;
$this->memcache = new Memcache;
$host = isset($config['host']) ? $config['host'] : 'localhost';
$port = isset($config['port']) ? $config['port'] : 11211;
$timeout = isset($config['timeout']) ? $config['timeout'] : 1;
$this->memcache->connect($host, $port, $timeout);
}
public function getAccessToken($access_token)
{
$cacheKey = 'storage-'.$access_token;
# Try and get from memory
$accessToken = $this->memcache->get($cacheKey);
# We have some data
if(!empty($accessToken)) {
return $accessToken;
}
$accessToken = $this->storage->getAccessToken('access_token');
$this->memcache->set($cacheKey, $accessToken, 0, strtotime($accessToken['expires']));
return $accessToken;
}
public function setAccessToken($oauth_token, $client_id, $user_id, $expires, $scope = null)
{
$cacheKey = 'storage-'.$oauth_token;
$this->storage->setAccessToken($oauth_token, $client_id, $user_id, $expires, $scope);
$updatedAccessToken = $this->storage->getAccessToken($oauth_token);
$result = $this->memcache->replace($cacheKey, $updatedAccessToken, 0, $expires);
if( $result == false )
{
$result = $this->memcache->set($cacheKey, $updatedAccessToken, 0, $expires);
}
}
} For use it just do try {
$pdotokenStorage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));
}catch(PDOException $e) {
//Send email with error
Yii::app()->EmailSenderComponent->send('Database Error', $e->getMessage());
//Log the error
Yii::log('Database error :'.$e->getMessage(), 'error', 'application.ApiController.init');
$this->_sendResponse(500, json_encode(array ('status'=> 500, 'message'=> 'Internal error contact the admin', 'code'=> 20003)), array('Content-type' => 'application/json') );
}
// USING PDOMEMCACHE
$tokenStorage = new OAuth2\Storage\MemCacheToken($pdotokenStorage); You can also pass an array of parameter to choose wich MemCache server you want to connect |
I created a pull request #608 |
I am using memory for users_credentials and access_token I am using grant_type 'password' I am succesfull validating user with memory saved user_credential and token the problem is when getting a new token it is not saved to memory again do not know how to implement this kind of funcionality
What I am doing is:
This is done on my controller init method I think it is overwriting everytime so I am not able to generate new tokens in memory, the PDO solution works geat but doing some kind of apache benchmark it shows that is 100x slower than doing in memory, I will be checking many tokens per second so the fastest I can do it the better, it would be great to suppor MemCache as well I will investigate if I can do it and make a pull request.
I inspected code and see that TokenController calls:
and it returns:
and at the end in te createAccessToken it calls:
In my case tokenStorage is memory but I do not see news token persisted, maybe you have a php server in memory running, or do you save to session or something
I am doing an api using Yii is kind of easy integrate it with your library and it would be great to have it merged next releases of Yii if I make it work I will share code to make this library work with Yii .
Thank you, you all
The text was updated successfully, but these errors were encountered: