Lumen Database Queue first job always failing Allowed memory exhausted - queue

I have a very odd situation where I set up a job to run in my Lumen database queue and all but the first job is processed. I do keep getting this particular error:
[2017-12-12 22:07:10] lumen.ERROR: Symfony\Component\Debug\Exception\FatalErrorException: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 702558208 bytes) in /var/www/vhosts/XXXXXXXXX$
Stack trace:
#0 /var/www/vhosts/XXXXXXXX/vendor/laravel/lumen-framework/src/Concerns/RegistersExceptionHandlers.php(54): Laravel\Lumen\Application->handleShutdown()
#1 [internal function]: Laravel\Lumen\Application->Laravel\Lumen\Concerns\{closure}()
#2 {main}
I have tried allowing the memory limit to go up but I keep getting the same error with differing values for the exhausted memory.
I find it very odd that it is always the first job and all of the rest of the jobs run perfectly fine. Should I be looking for bad data in the first job?
My code basically looks like this:
This is my Command file
namespace App\Console\Commands;
use App\Jobs\UpdateNNNAppListJob;
use Illuminate\Console\Command;
use App\Services\MiddlewareApi;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Mockery\Exception;
use Illuminate\Support\Facades\Queue;
class AddEmailsToAppList extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'addemails:nnnmobileapp';
/**
* The console command description.
*
* #var string
*/
protected $description = 'This will add all mobile app users in the database to the nnn mobile app list.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
public function handle()
{
$chunkSize = 500; //this is the most middleware can handle with its bulk signup call
$emailChunks = $this->getEmailsToAdd($chunkSize);
$jobDelay = 120; //time between queued jobs
$jobDelayTimeKeeper = 60; //This will be the actual time delay that will be put into the later method
foreach ($emailChunks as $emailChunk) {
Queue::later($jobDelayTimeKeeper, new UpdateMmpAppListJob($emailChunk));
$jobDelayTimeKeeper = $jobDelayTimeKeeper + $jobDelay;
}
}
public function getEmailsToAdd($chunkSize)
{
$emails = DB::table('app_users')
->join('app_datas', 'app_datas.customer_number', '=', 'app_users.customer_number')
->select('app_users.email')
->get()
->chunk($chunkSize);
return $emails;
}
}
Here is my Job File
<?php
namespace App\Jobs;
use App\Services\MiddlewareApi;
use Illuminate\Support\Facades\Log;
use Mockery\Exception;
class UpdateMmpAppListJob extends Job
{
/**
* Array of emails to update list with
* #var array
*/
protected $emailArray;
/**
* The number of times the job may be attempted.
*
* #var int
*/
public $tries = 2;
public function __construct($emailArray)
{
$this->emailArray = $emailArray;
}
public function handle()
{
$listCodeToAddTo = 'NNNAPP';
$sourceId = 'NNNNNNN';
$middlewareApi = new MiddlewareApi();
try {
$middlewareApi->post_add_customer_signup_bulk($listCodeToAddTo, $this->emailArray, $sourceId);
} catch (\Exception $e) {
Log::error('An error occurred with theUpdateMmpAppListJob: ' . $e);
mail('djarrin#NNN.com', 'UpdateNnnAppListJob Failure', 'A failure in the UpdateNnnAppListJob, here is the exception: ' . $e);
}
}
public function failed(\Exception $exception)
{
mail('djarrin#moneymappress.com', 'Push Processor Que Failure', 'A failure in the UpdateMmpAppListJob, here is the exception: ' . $exception);
}
}
Any help/suggestions on this issue would be appreciate.

Your code calls ->get() which will load the entire result into memory. This causes the huge memory allocation that you're seeing. Remove it and let ->chunk(...) work with the database builder instead of the in-memory Collection that get() has returned. You would also have to provide a callback to chunk that processes every chunk.
public function handle() {
$chunkSize = 500; //this is the most middleware can handle with its bulk signup call
$jobDelay = 120; //time between queued jobs
$jobDelayTimeKeeper = 60; //This will be the actual time delay that will be put into the later method
DB::table('app_users')
->join('app_datas', 'app_datas.customer_number', '=', 'app_users.customer_number')
->select('app_users.email')
->chunk($chunkSize, function($emailChunk) use (&$jobDelayTimeKeeper, $jobDelay) {
Queue::later($jobDelayTimeKeeper, new UpdateMmpAppListJob($emailChunk));
$jobDelayTimeKeeper = $jobDelayTimeKeeper + $jobDelay;
});
}

The above concept is correct but this syntax was required to get past the
[2017-12-14 22:08:26] lumen.ERROR: RuntimeException: You must specify an orderBy clause when using this function. in /home/vagrant/sites/nnn/vendor/illuminate/database/Query/Builder.php:1877
This is for Lumen 5.5:
public function handle()
{
$chunkSize = 500; //this is the most middleware can handle with its bulk signup call
$jobDelay = 120; //time between queued jobs
$jobDelayTimeKeeper = 60; //This will be the actual time delay that will be put into the later method
$emails = DB::table('app_users')
->join('app_datas', 'app_datas.customer_number', '=', 'app_users.customer_number')
->select('app_users.email')->orderBy('app_users.id', 'desc');
$emails->chunk($chunkSize, function($emailChunk) use (&$jobDelayTimeKeeper, $jobDelay) {
Queue::later($jobDelayTimeKeeper, new UpdateMmpAppListJob($emailChunk));
$jobDelayTimeKeeper = $jobDelayTimeKeeper + $jobDelay;
});
}

Related

How do I get uid of a File Reference Object in TYPO3?

I am trying to get a file through this code $f = $resourceFactory->getFileObject($uid); but the problem is the uid is a protected field in the file reference object, as seen below so I am not able to get the uid, and getUid() obviously wont work either.
So how can I get the uid of the file reference (FAL)
/**
* A file reference object (File Abstraction Layer)
*
* #api experimental! This class is experimental and subject to change!
*/
class FileReference extends
\TYPO3\CMS\Extbase\Domain\Model\AbstractFileFolder
{
/**
* Uid of the referenced sys_file. Needed for extbase to serialize the
* reference correctly.
*
* #var int
*/
protected $uidLocal;
/**
* #param \TYPO3\CMS\Core\Resource\ResourceInterface $originalResource
*/
public function setOriginalResource(\TYPO3\CMS\Core\Resource\ResourceInterface $originalResource)
{
$this->originalResource = $originalResource;
$this->uidLocal = (int)$originalResource->getOriginalFile()->getUid();
}
/**
* #return \TYPO3\CMS\Core\Resource\FileReference
*/
public function getOriginalResource()
{
if ($this->originalResource === null) {
$this->originalResource = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileReferenceObject($this->getUid());
}
return $this->originalResource;
}
}
Given you have an instance of TYPO3\CMS\Extbase\Domain\Model\FileReference then you can use getOriginalResource() to get the wrapped TYPO3\CMS\Core\Resource\FileReference. If you need the referenced file, you can then use getOriginalFile(). Thus as a chained call:
$file = $fileReference->getOriginalResource()->getOriginalFile();
Notice that you don't have to use the ResourceFactory yourself in all of this, this is taken care of internally.
Work form me.
You can find or get file refernce uid using custom query.
In Controller :
$uid = $yourObject->getUid();
$fileReference = $this->yourRepository->getFileReferenceObject($uid);
In Repository
public function getFileRefernceHeaderLogo($uid){
$query = $this->createQuery();
$queryString = "SELECT *
FROM sys_file_reference
WHERE deleted = 0
AND hidden = 0
AND tablenames='your_table_name'
AND fieldname='your_field_name'
AND uid_foreign =".$uid;
$query->statement($queryString);
return $res = $query->execute(true);
}
In Controller
$fileRefUid = $fileReference[0]['uid'];
Here you can get uid of file reference table.It is long process.
You can also get sys_file table uid for getFileObject.like,
$sys_file_uid = $fileReference[0]['uid_local'];

Doctrine Custom ID with auto increment

I want to define some id with prefix.
For example, for one order entity its : "OR17000001"
In this example, the prefix is "OR17"
So i have declare my id entities like this :
/**
* #var string
*
* #ORM\Column(name="id", type="string", length=8)
* #ORM\Id
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class="My\Bundle\Generator\OrderCodeGenerator")
*/
private $id;
And my Generator is :
<?php
namespace My\Bundle\Generator;
use Doctrine\ORM\Id\AbstractIdGenerator;
use Doctrine\ORM\EntityManager;
use My\Bundle\Entity\Order;
class OrderCodeGenerator extends AbstractIdGenerator
{
/**
* Format :
* $prefix - string
* $year - take 2 first letters (17)
* $increment - Take the last code + 1
*
* #param EntityManager $em
* #param \Doctrine\ORM\Mapping\Entity $entity
* #return bool|string
*/
public function generate(EntityManager $em, $entity)
{
if ($entity instanceof Order) {
$now = new \DateTime();
$year = $now->format('y');
$prefix = 'OR';
$maxCode = $em->getRepository('MyRepo:Order')->findMaxCode($year, $prefix);
if ($maxCode) {
$increment = substr($maxCode[1], -4);
$increment = (int)$increment + 1;
} else
$increment = 0;
$code = $prefix . $year . sprintf('%04d', $increment);
return $code;
}
return false;
}
}
Without forget the method findMaxCode :
public function findMaxCode($year, $prefix)
{
$qb = $this->createQueryBuilder('entity');
$qb->where($qb->expr()->like('entity.id', ':code'))
->setParameter('code', '%' . $prefix . $year . '%');
$qb->select($qb->expr()->max('entity.id'));
return $qb->getQuery()->getOneOrNullResult();
}
That's work fine =)
My problem is when i try to add some entities in same time.
My case is :
Order entity with some items (its a form collection)
Item entity
So i need to custom id of Items Order with this strategy. And the problem is for found the max code. I have this error :
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicata du
champ 'IT170000001' pour la clef 'PRIMARY'
The generator can't found the max code for generate the second item, because there is no flush.
How can i save the increment value between 2 id generation before the flush ??
Solution :
I keep numeric id for my Item. Its useful for my Order entity, its more readable than an simple int. But i don't care for Item.
Thx to Honza Rydrych
Querying DB for last inserted ID and then inserting "+one" isn't reliable solution.
My solution for this case would be let doctrine generate ID's by the standard way and add the prefix "OR/Year/" when you need to present the data.
(Optionaly you can write custom Twig extension for presenting the ID http://symfony.com/doc/current/templating/twig_extension.html)

TYPO3: Set more than one storage pid for one extension

I builded an extension that has a 'details' table that holds details with a title and a description that be included inline to another object. Right now new details are stored in the same pid as the object, but I'd like to change that.
this question was answered by Merec and in the comments he points to a solution (add the column "pid" to your model, this is the first the model looks at) but asked to formulate a separate question for it ...
I took his suggestion but could not get it to work, so here is the separate question, in addition I would like to know how to get a value from the configuration to be used as pid for this.
update: René Pflamm pointed out that I should underline that I'm trying to set this Pid for saving in the backend, not in the frontend ... I basically recognized this destinction later on
my constants.ts :
plugin.tx_myext {
persistence {
# cat=plugin.tx_myext/storage/a; type=string; label=Default storage PID
defaultStoragePid =
# cat=plugin.tx_myext/storage/a; type=string; label=Details storage PID
detailsStoragePid =
}
}
my setup.ts
plugin.tx_myext {
persistence {
storagePid = {$plugin.tx_myext.persistence.defaultStoragePid}
detailPid = {$plugin.tx_myext.persistence.detailsStoragePid}
}
}
I am not sure if I understood you correctly but you can tell extbase to look in multiple pids for your records and state for each record where it should be stored:
plugin.tx_myext {
persistence {
storagePid = {$plugin.tx_myext.persistence.defaultStoragePid},{$plugin.tx_myext.persistence.detailStoragePid}
classes {
Vendor\MyExt\Domain\Model\Detail {
newRecordStoragePid = {$plugin.tx_myext.persistence.detailStoragePid}
}
}
}
}
Models inherits from TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject which has getter and setter for $pid. If you set the field, all automation to set the field (i.e. newRecordStoragePid in typoscript) are not used.
With this, you can set all storage locations you want.
$myModel = $this->objectManager->create('Vendor\\Namespace\\Domain\\Model\\MyModel');
$myModel->setPid(4321);
Part from TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject:
/**
* #var int The id of the page the record is "stored".
*/
protected $pid;
/**
* Setter for the pid.
*
* #param int|NULL $pid
* #return void
*/
public function setPid($pid)
{
if ($pid === null) {
$this->pid = null;
} else {
$this->pid = (int)$pid;
}
}
/**
* Getter for the pid.
*
* #return int The pid or NULL if none set yet.
*/
public function getPid()
{
if ($this->pid === null) {
return null;
} else {
return (int)$this->pid;
}
}
You can, when create elements in your extension, say the model which pid should be use.
In your TS:
plugin.tx_myext.settings {
detailPid = {$plugin.tx_myext.persistence.detailsStoragePid}
}
In your code above it can look like:
public function createDetailsAction(Detail $detail) {
$detail->setPid($this->settings['detailPid']);
$this->detailRepository->add($detail);
}

How to dynamically change serialized groups in symfony jms fosrestbundle?

Hello I'd like to dynamically change the groups of my serialization context.
The code :
/**
* #Rest\Get("", name="bap_api_space_query")
* #Rest\View(serializerGroups={"Default", "space_dashboard", "dashboard_resource"})
*
* #ApiDoc(resource=true,description="List all spaces this user has access to")
*/
public function queryAction(Request $request)
{
$user = $this->getUser()->reload();
$organization = $user->getOrganization();
// depending the request, remove or add serialized group
// for example $view->setSerializationGroups('dashboard');
return $organization->getSpaces();
}
As commented in the code, i'd like to remove or add group in the controller .
Is there a way to do it ?
The solution is pretty easy after 5hours of research :
public function queryAction(Request $request)
{
$user = $this->getUser()->reload();
$organization = $user->getOrganization();
// filter spaces where org has an active contract
$context = new Context();
$context->setGroups(array('Default'));
$spaces = $organization->getSpaces();
$view = $this->view($spaces, 200);
$view->setContext($context);
return $this->handleView($view);
}

Maximum execution time exceeds due to session start?

I am getting following error when I use Zend_Session::Start() in my bootstrap file.
Maximum execution time of 30 seconds exceeded in G:\wamp\library\Zend\Session.php on line 480
On line 480 of Zend\Session.php code is
$startedCleanly = session_start();
The browser keeps loading the page like forever due to it , its like infinite while loop .
Context
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected $_config;
protected $_acl;
protected $_auth;
public function _initMyAutoloader()
{
$autloader = Zend_Loader_Autoloader::getInstance();
$autloader->pushAutoloader(new Zend_Application_Module_Autoloader(array('basePath'=>APPLICATION_PATH . '/','namespace'=>'')));
return $autloader ;
}
public function _initMyConfig()
{
Zend_Session::start();
$this->_config = new Zend_Config($this->getOptions());
Zend_Registry::set('config',$this->_config);
return $this->_config;
}
Thanks.
It's not because of session, but max_execution_time.
max_execution_time can be set in php.ini, so you can modify it:
max_execution_time = 60 ; Maximum execution time of each script, in seconds