
Elastic::Model::Scope - Keeps objects alive and connected

version 0.26

Elastic::Model::Scope is an optional in-memory cache, which serves three purposes:
See Elastic::Manual::Scoping for a fuller discussion of when and how to use scoping.

The parent scope of this scope, or UNDEF.

The logic used in scopes is best explained by the examples below:
$obj = $scope->get_object($domain_name, $uid);
When calling "get()" in Elastic::Model::Domain or "get_doc()" in Elastic::Model::Role::Model to retrieve an object from ElasticSearch, we first check to see if we can return the object from our in-memory cache by calling "get_object()":
If an object with the same namespace_name/type/id exists in the CURRENT scope (and its version is as least as high as the requested version, if any) then we return the SAME object.
$scope = $model->new_scope;
$one = $domain->get( user => 123 );
$two = $domain->get( user => 123 );
print $one->name;
# Clint
$two->name('John');
print $one->name;
# John
print refaddr($one) == refaddr($two) ? 'TRUE' : 'FALSE';
# TRUE
If an object with the same domain_name/type/id exists in the PARENT scope (and its version is as least as high as the requested version, if any) then we return a CLONE of the object. (Note: we clone the original object as it was when loaded from ElasticSearch. Any unsaved changes are ignored.)
$scope_1 = $model->new_scope;
$one = $domain->get( user => 123 );
print $one->name;
# Clint
$one->name('John');
$scope_2 = $model->new_scope;
$two = $domain->get( user => 123 );
print $two->name;
# Clint
print refaddr($one) == refaddr($two) ? 'TRUE' : 'FALSE';
# FALSE
Otherwise the calling method will fetch the object from ElasticSearch itself, and store it in the current scope.
If the object exists in the same scope or a parent scope, but it is an Elastic::Model::Deleted object, then we return undef.
$object = $scope->store_object($ns_name, $object);
When we load a object that doesn't exist in the current scope or in any of its parents, or we create-a-new or update-an-existing object via "save()" in Elastic::Model::Role::Doc, we also store it in the current scope via "store_object()".
$scope_1 = $model->new_scope;
$one = $domain->get( user => 123 );
print $one->name;
# Clint
$scope_2 = $model->new_scope;
$two = $domain->get( user => 123 );
print $two->name;
# Clint
print refaddr($one) == refaddr($two) ? 'TRUE' : 'FALSE';
# FALSE
Now we update the $one object, while $scope_2 is current, and save it:
$one->name('John');
$one->save;
Object $one is now in $scope_1 AND $scope_2.
$three = $domain->get( user => 123 );
print $three->name;
# John
print refaddr($one) == refaddr($three) ? 'TRUE' : 'FALSE';
# TRUE
Object $two still exists, and is still kept alive, but will no longer be returned from $scope_2.
print $two->name;
# Clint
$scope->delete_object( $ns_name, $uid );
When calling "delete_doc()" in Elastic::Model::Role::Model, "delete_doc()" in Elastic::Model::Domain or "delete()" in Elastic::Model::Role::Doc we check to see if an object with the same UID (namespace_name/type/id) exists in the current scope.
If it does, we rebless it into Elastic::Model::Deleted. Otherwise, we create a new Elastic::Model::Deleted object with the $uid and store that in the current scope.
$scope_1 = $model->new_scope;
$one = $domain->get( user => 1 );
$domain->delete (user => 1 );
print $domain->isa('Elastic::Model::Deleted') ? 'TRUE' : 'FALSE';
# TRUE
print $one->name; # Throws an error,
$scope_1 = $model->new_scope;
$one = $domain->get( user => 1 );
$scope_2 = $model->new_scope;
$domain->delete( user => 1);
$two = $domain->get( user => 1 ); # Throws an error
print $one->name;
# Clint
undef $scope_2;
$two = $domain->get( user => 1 );
print refaddr($one) == refaddr($two) ? 'TRUE' : 'FALSE';
# TRUE
But, calling delete() on an object which isn't in the current scope still affects that object:
$scope_1 = $model->new_scope;
$one = $domain->get( user => 1 );
$scope_2 = $model->new_scope;
$one->delete;
print $one->name; # Throws an error

Clinton Gormley <drtech@cpan.org>

This software is copyright (c) 2013 by Clinton Gormley.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.