Setting the Symfony session storage factory - session

I'm using Symfony 6 to refactor a CodeIgniter 3 framework. User logging in is done via CodeIgniter so I'd like to read the CI session data (stored in a DB) in Symfony.
I'm trying to use my own session storage factory because the CI session name is dynamically constructed using the hostname and also because of the way CI stores the session in the db is different to Symfony.
I've set the session storage factory in framework.yaml
# config/packages/framework.yaml
session:
storage_factory_id: App\Service\CINativeSessionStorageFactory
And I've configured my services (including my own PDO session handler):
# config/services.yaml
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind: # defines the scalar arguments once and apply them to any service defined/created in this file
string $locales: '%app_locales%'
string $defaultLocale: '%locale%'
string $emailSender: '%app.notifications.email_sender%'
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# CodeIgniter Session handler
App\Service\CIPdoSessionHandler:
arguments:
- '%env(DATABASE_URL)%'
- {
db_table: 'ci_sessions',
db_id_col: 'id',
db_data_col: 'data',
db_time_col: 'timestamp',
db_lifetime_col: 'sess_lifetime'
}
properties:
logger: '#logger'
tags:
- { name: monolog.logger, channel: session }
App\Service\CINativeSessionStorageFactory:
arguments:
$handler : '#App\Service\CIPdoSessionHandler'
$options : {
cookie_secure: auto,
cookie_samesite: lax,
gc_maxlifetime: 7200
}
tags:
- { name: monolog.logger, channel: session }
However I am getting these errors in the logs:
[2022-11-30T17:32:16.738059+00:00] php.CRITICAL: Fatal Compile Error: Cannot declare class App\Service\CINativeSessionStorageFactory, because the name is already in use {"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0): Compile Error: Cannot declare class App\\Service\\CINativeSessionStorageFactory, because the name is already in use at /workspace/symfony/src/Service/CINativeSessionStorageFactory.php:16)"} []
[2022-11-30T17:32:16.739841+00:00] request.CRITICAL: Uncaught PHP Exception Symfony\Component\ErrorHandler\Error\FatalError: "Compile Error: Cannot declare class App\Service\CINativeSessionStorageFactory, because the name is already in use" at /workspace/symfony/src/Service/CINativeSessionStorageFactory.php line 16 {"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0): Compile Error: Cannot declare class App\\Service\\CINativeSessionStorageFactory, because the name is already in use at /workspace/symfony/src/Service/CINativeSessionStorageFactory.php:16)"} []
[2022-11-30T17:32:16.741681+00:00] session.DEBUG: Using App\Service\CIPdoSessionHandler [] []
[2022-11-30T17:32:16.741839+00:00] session.DEBUG: Setting session name to ci_session_XXXXXXX [] []
The last two lines indicate that my storage factory is working (at least partially) so I'm unsure as why I'm getting these errors.
The first part of my question is: Where am I going wrong?
As an aside, I noticed that if I set up my framework.yaml like this:
# config/packages/framework.yaml
session:
handler_id: App\Service\CIPdoSessionHandler
storage_factory_id: App\Service\CINativeSessionStorageFactory
Then the handler passed to my constructor was always null
public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface $handler = null, MetadataBag $metaBag = null, bool $secure = false)
{
// $handler is null!
So the second part of my question is: Do handler_id and storage_factory_id not work together?
Some additional information from trying to debug this issue:
If I save config/services.yaml and then refresh the page - I don't get this message.
If I then refresh the page again - I get the error message.
If I then save config/services.yaml again and refresh the page - I don't get this message
... etc
Is my installation broken? I followed the steps here : https://symfony.com/doc/current/setup.html

Related

CDK/CloudFormation Batch Setup NotStabilized Error

I'm trying to set up a simple Batch Compute Environment using a LaunchTemplate, so that I can specify a larger-than-default volume size:
const templateName = 'my-template'
const jobLaunchTemplate = new ec2.LaunchTemplate(stack, 'Template', {
launchTemplateName: templateName,
blockDevices: [ ..vol config .. ]
})
const computeEnv = new batch.CfnComputeEnvironment(stack, 'CompEnvironment', {
type: 'managed',
computeResources: {
instanceRole: jobRole.roleName,
instanceTypes: [
InstanceType.of(InstanceClass.C4, InstanceSize.LARGE).toString()
],
maxvCpus: 64,
minvCpus: 0,
desiredvCpus: 0,
subnets: vpc.publicSubnets.map(sn => sn.subnetId),
securityGroupIds: [vpc.vpcDefaultSecurityGroup],
type: 'EC2',
launchTemplate: {
launchTemplateName: templateName,
}
},
})
They both initialize fine when not linked, however as soon as the launchTemplate block is added to the compute environment, I get the following error:
Error: Resource handler returned message: "Resource of type 'AWS::Batch::ComputeEnvironment' with identifier 'compute-env-arn' did not stabilize." (RequestToken: token, HandlerErrorCode: NotStabilized)
Any suggestions are greatly appreciated, thanks in advance!
For anyone running into this - check the resource that is being created in the AWS Console - i.e go to aws.amazon.com and refresh the page over and over until you see it created by CF. This gave me a different error message regarding the instance profile not existing (A bit more helpful than the terminal error...)
A simple CfnInstanceProfile did the trick:
new iam.CfnInstanceProfile(stack, "batchInstanceProfile", {
instanceProfileName: jobRole.roleName,
roles: [jobRole.roleName],
});
I faced similar error.
But in my case cdk had created subnetGroups list in cdk.context.json and was trying to use the same in the CfnComputeEnvironment definition.
The problem was; I was using the default vpc and had manually modified few subnets. and cdk.context.json was not updated.
Solved by deleting the cdk.context.json
This file was recreated with correct values in next synth.
Tip for others facing similar problem:
Don't just rely on the error message; watch closely the Cloud-formation Script that's generated from CDK for the resource.

How to set namespace and item expiration for a symfony5 redis cachepool

I try to configure two cache pools in my Synfony5 app to use a certain namespace and set a default expiration date for the items. After trying for the umpteenth time the umteenth variation I get the feeling that my configuration is going in circles.
What I understood so far:
In the constructor of the RedisAdapter you can set the namespace and the default expiration time
In the createConnection method you set the url of your redis server.
However the constructor of the RedisAdapter seems to already need a redis client (= redis connection?)
RedisAdapter:
/**
* #param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client
* #param string $namespace The default namespace
* #param int $defaultLifetime The default lifetime
*/
public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
$this->init($redisClient, $namespace, $defaultLifetime, $marshaller);
}
How can I inject my namespaces and defaultLifetimes into the RedisAdapter?
What I tried so far:
cache.yaml:
framework:
cache:
pools:
cache.sap:
adapter: cache.adapter.redis
provider: app.service.puc_sap_redis_adapter
cache.pers:
adapter: cache.adapter.redis
provider: app.service.puc_pers_redis_adapter
services.yaml:
app.my_redis_adapter:
class: 'Redis'
factory: ['Symfony\Component\Cache\Adapter\RedisAdapter', 'createConnection']
arguments:
- 'redis://%env(string:REDIS_URL)%:%env(int:REDIS_PORT)%'
- { retry_interval: 2, timeout: 5 }
app.service.puc_sap_redis_adapter:
class: Symfony\Component\Cache\Adapter\RedisAdapter
arguments:
$redisClient: '#app.my_redis_adapter'
$namespace: 'sapData'
$defaultLifetime: '%env(SAP_CACHE_TIMEOUT)%'
app.service.puc_pers_redis_adapter:
class: Symfony\Component\Cache\Adapter\RedisAdapter
arguments:
$redisClient: '#app.my_redis_adapter'
$namespace: 'persData'
$defaultLifetime: '%env(CACHE_TIMEOUT)%'
This gets me the error message:
line: 62,
file: "/var/www/vendor/symfony/cache/Traits/RedisTrait.php",
message: "\"Symfony\\Component\\Cache\\Traits\\RedisTrait::init()\"
expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\\ClientInterface,
\"Symfony\\Component\\Cache\\Adapter\\RedisAdapter\" given."
How can I configure the namespaces and expiration time for my two cache pools?
After several days of blood, sweat and tears I leave this here so nobody else will have to experience this deep desperation.
This is how it works. You will need no extra class "just" this nifty cache.yaml in the folder for your environment:
framework:
cache:
pools:
cache.sap:
adapter: app.cache.adapter.sap_redis # custom namespace and item expiration defined there
provider: app.cache.custom_redis_provider # Which server connection should be used
cache.pers:
adapter: app.cache.adapter.pers_redis # custom namespace and item expiration defined there
provider: app.cache.custom_redis_provider # Which server connection should be used
services:
app.cache.custom_redis_provider: # this defines our connection to the redis server
class: \Redis
factory: ['Symfony\Component\Cache\Adapter\RedisAdapter', 'createConnection']
arguments:
- 'redis://%env(string:REDIS_URL)%:%env(int:REDIS_PORT)%' # this defines the url to the redis server. "redis" up front is mandatory
- { retry_interval: 2, timeout: 5 } # defines number of connection retries and connection timeout (not item expiration!)
app.cache.adapter.sap_redis: # here we pass namespace and expiration timeout into the constructor of the redis adapter
parent: 'cache.adapter.redis'
tags:
- { name: 'cache.pool', namespace: 'sapData', default_lifetime: '%env(int:SAP_CACHE_TIMEOUT)%' }
app.cache.adapter.pers_redis: # here we pass a different namespace and expiration timeout into the constructor of the redis adapter
parent: 'cache.adapter.redis'
tags:
- { name: 'cache.pool', namespace: 'persData', default_lifetime: '%env(int:CACHE_TIMEOUT)%' }
You can also set those parameters within the usual cache-pool configuration.
framework:
cache:
default_memcached_provider: 'memcached://localhost'
# could also replace with
# default_redis_provider: 'redis://localhost' # or '%env(REDIS_DSN)%'
pools:
# creates a "custom_thing.cache" service
# autowireable via "CacheInterface $customThingCache"
# uses the "app" cache configuration
custom_thing.cache:
adapter: cache.app
# creates a "my_cache_pool" service
# autowireable via "CacheInterface $myCachePool"
my_cache_pool:
adapter: cache.adapter.filesystem
# uses the default_memcached_provider from above
acme.cache:
adapter: cache.adapter.memcached
# control adapter's configuration - customised provider adaptor & DSN
foobar.cache:
adapter: cache.adapter.memcached
provider: 'memcached://user:password#example.com'
# uses the "foobar.cache" pool as its backend but controls
# the lifetime and (like all pools) has a separate cache namespace
short_cache:
adapter: foobar.cache
default_lifetime: 60
The page (linked above) goes on to say how to tag a service for a specific namespace, but the various configured pools already have one set by default:
Each pool manages a set of independent cache keys: keys from different pools never collide, even if they share the same backend. This is achieved by prefixing keys with a namespace that’s generated by hashing the name of the pool, the name of the compiled container class and a configurable seed that defaults to the project directory.

Terraform Custom provider - Resource support error

I created a custom provider to use an internal API used for generating approved names for resources according to our standard. I wrote it with Go, but when I'm testing it, I'm getting an error saying:
Error: meaningful_resource_name.server_name: Provider doesn't support resource: meaningful_resource_name
Here's the test tf file I'm using:
resource "meaningful_resource_name" "server_name" {
<... parameters ...>
}
output "server_name" {
value = "${meaningful_resource_name.server_name.name}"
}
And this is the provider.go file:
package meaningful
import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
func Provider() terraform.ResourceProvider {
return &schema.Provider{
Schema: map[string]*schema.Schema{},
ResourcesMap: map[string]*schema.Resource{
"meaningful_resource_name": meaningfulName(),
},
DataSourcesMap: map[string]*schema.Resource{},
}
}
I already created a provider using this same structure, but I don't understand why it's not recognizing it. Any clues?
I'm using Go v1.10.4 and Terraform v0.11.10

Shopware installation error: Identifier DB not initialized yet

After installation wizard is finished I get this error.
Slim Application Error
The application could not run because of the following error:
Details
Type: RuntimeException
Message: Identifier DB not initialized yet
File: /.../recovery/install/src/ContainerProvider.php
Line: 162
Is there is some configuration file where I can set DB params? I had insert all params via installation wizard.
In file recovery/install/src/ContainerProvider.php
Add 2 strings:
In use-section
use Shopware\Recovery\Update\Utils;
2.Inside the register-function:
$container['db'] = function ($c) {
$conn = Utils::getConnection(SW_PATH);
return $conn;
};

How do I use env.DATABASE_URL with Loopback in Heroku?

I've removed datasources.json and added a datasources.local.js file.
var postgresURI = process.env.DATABASE_URL;
module.exports = {
db: {
defaultForType: 'postgresql',
connector: 'postgresql',
url: postgresURI
}
};
In model-config.json I have "dataSource": "db" set for all sections.
It throws the following error: User is referencing a dataSource that does not exist: "db".
I understand the error but not why it's being thrown. What I am doing wrong?
As documentation says:
You can override values set in datasources.json in the following files: datasources.local.js or datasources.local.json
So instead of removing datasources.json you might want to keep it with a declaration of "db" in it. While in "datasources.local.js" you need to override environment specific setting which is the url.

Resources