Curio::Factory - Definer, creator, provider, and holder of Curio objects.


    my $factory = MyApp::Service::Cache->factory();


The factory object contains the vast majority of Curio's logic. Each Curio class (Moo classes who consume Curio::Role) gets a single factory object created for them via "initialize" in Curio::Role.

Note that much of the example code in this documentation is based on the "SYNOPSIS" in Curio. Also when you see the term "Curio object" it is referring to instances of "class".



    class => 'MyApp::Service::Cache',

The Curio class that this factory uses to instantiate Curio objects.

This is automatically set by "initialize" in Curio::Role.



    does_registry => 1,
    resource_method_name => 'chi',

Causes the resource of all Curio objects to be automatically registered so that "find_curio" may function.

Defaults off (0), meaning "find_curio" will always return undef.


    resource_method_name => 'chi',

The method name in the Curio class to retrieve the resource that it holds. A resource is whatever "thing" the Curio class encapsulates. In the case of the example in "SYNOPSIS" in Curio the resource is the CHI object which is accessible via the chi method.

It is still your job to create the method in the Curio class that this argument refers to, such as:

    has chi => ( is=>'lazy', ... );

This argument must be defined in order for fetch_resource and "does_registry" to work, otherwise they will have no way to know how to get at the resource object.

This defaults to the string resource.


    does_registry => 1,
    resource_method_name => 'chi',
    installs_curio_method => 1,

This causes a curio() method to be installed in all resource object classes. The method calls "find_curio" and returns it, allowing for reverse lookups from resource objects to curio objects.

"does_registry" must be set for this to function.


    does_caching => 1,

When caching is enabled all calls to "fetch_curio" will attempt to retrieve from an in-memory cache.

Defaults off (0), meaning all fetch calls will return a new Curio object.


    cache_per_process 1,

Some resource objects do not like to be created in one process and then used in others. When enabled this will add the current process's PID and thread ID (if threads are enabled) to the key used to cache the Curio object.

If either of these process IDs change then fetch will not re-use the cached Curio object from a different process and will create a new Curio object under the new process IDs.

Defaults to off (0), meaning the same Curio objects will be used by fetch across all forks and threads.

Normally the default works fine. Some CHI drivers need this turned on.


    export_function_name => 'myapp_cache',

The export function is exported when the the Curio class is imported, as in:

    use MyApp::Service::Cache;
    my $chi = myapp_cache( $key );

See also "always_export" and "export_resource".


    always_export => 1,

When enabled this causes the export function to be always exported.

    use MyApp::Service::Cache;

When this option is not set you must explicitly request that the export function be exported.

    use MyApp::Service::Cache qw( myapp_cache );


    export_resource => 1,

Rather than returning the curio object this will cause the resource object to be returned by the export function. Requires that "resource_method_name" be set.


    does_keys => 1,

Turning this on allows a key argument to be passed to "fetch_curio" and many other methods. Typically, though, you don't have to set this as you'll be using "add_key" which automatically turns this on.

By enabling keys this allows "fetch_curio", caching, resource registration, injecting, and anything else dealing with a Curio object to deal with multiple Curio objects based on the passed key argument.

Defaults to off (0), meaning the factory will only ever manage a single Curio object.


    allow_undeclared_keys => 1,

When "fetch_curio", and other key-accepting methods are called, they normally throw an exception if the passed key has not already been declared with "add_key". By allowing undeclared keys any key may be passed, which can be useful especially if coupled with "key_argument".

Defaults to off (0), meaning keys must always be declared before being used.


    default_key => 'generic',

If no key is passed to key-accepting methods like "fetch_curio" then they will use this default key if available.

Defaults to no default key.


    key_argument => 'connection_key',

When set, this causes an extra argument to be passed to the Curio class during object instantiation. The argument's key will be whatever you set key_argument to and the value will be the key used to fetch the Curio object.

You will still need to write the code in your Curio class to capture the argument, such as:

    has connection_key => ( is=>'ro' );

Defaults to no key argument.


    default_arguments => {
        arg => 'value',

When set, these arguments will be used when creating new instances of the Curio class.

Any other arguments such as those provided by "add_key" and "key_argument" will overwrite these default arguments.



    my $keys = $factory->keys();
    foreach my $key (@$keys) { ... }

Returns an array ref containing all the keys declared with "add_key".



    my $curio = $factory->fetch_curio();
    my $curio = $factory->fetch_curio( $key );

Returns a Curio object. If "does_caching" is enabled then a cached object may be returned.


    my $resource = $factory->fetch_resource();
    my $resource = $factory->fetch_resource( $key );

Like "fetch_curio", but always returns a resource.


    my $args = $factory->arguments();
    my $args = $factory->arguments( $key );

This method returns an arguments hashref that would be used to instantiate a new Curio object. You could, for example, use this to produce a base-line set of arguments, then sprinkle in some more, and make yourself a special mock object to be injected.


    $factory->add_key( $key, %arguments );

Declares a new key and turns "does_keys" on if it is not already turned on.

Arguments are optional, but if present they will be saved and used by "fetch_curio" when calling new() on "class".


    $factory->alias_key( $alias_key => $real_key );

Adds a key that is an alias to a key that was declared with "add_key". Alias keys can be used anywhere a declared key can be used.


    my $curio_object = $factory->find_curio( $resource );

Given a Curio object's resource this will return that Curio object for it.

This does a reverse lookup of sorts and can be useful in specialized situations where you have the resource, and you need to introspect back into the Curio object.

    # I have my $chi and nothing else.
    my $factory = MyApp::Service::Cache->factory();
    my $curio = $factory->find_curio( $chi );

This only works if you've enabled "does_registry", otherwise undef is always returned by this method.


    $factory->inject( $curio_object );
    $factory->inject( $key, $curio_object );

Takes a curio object of your making and forces "fetch_curio" to return the injected object (or the injected object's resource). This is useful for injecting mock objects in tests.


    my $guard = $factory->inject_with_guard(
    my $guard = $factory->inject_with_guard(
        $key, $curio_object,

This is just like "inject" except it returns an guard object which, when it leaves scope and is destroyed, will automatically "uninject".


    my $curio_object = $factory->uninject();
    my $curio_object = $factory->uninject( $key );

Removes the previously injected curio object, restoring the original behavior of "fetch_curio".

Returns the previously injected curio object.



    my $factory = Curio::Factory->find_factory( $class );

Given a Curio class this will return its factory object, or undef otherwise.


Copyright (C) 2019 Aran Clary Deltac

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see