Php 内存消耗优化

Php 内存消耗优化,php,laravel,optimization,guzzle,Php,Laravel,Optimization,Guzzle,我在Laravel中有一个服务类,它处理与API端点的集成,以获取记录并处理它们(在数据库中创建和更新) 我多次调用Guzzle实例,因为我必须为每个公司分支使用不同的API键调用API内点 我已将内存限制更改为3000MB,但尽管如此,有时代码执行会达到该内存量,并且进程会由于内存泄漏而失败。每次调用执行后,我都会使用memory\u get\u usage()获取内存使用情况(由于分页,我必须进行迭代) 在这个过程中有没有释放内存的方法或推荐的优化方法 代码如下: <?php nam

我在Laravel中有一个服务类,它处理与API端点的集成,以获取记录并处理它们(在数据库中创建和更新)

我多次调用Guzzle实例,因为我必须为每个公司分支使用不同的API键调用API内点

我已将内存限制更改为3000MB,但尽管如此,有时代码执行会达到该内存量,并且进程会由于内存泄漏而失败。每次调用执行后,我都会使用
memory\u get\u usage()
获取内存使用情况(由于分页,我必须进行迭代)

在这个过程中有没有释放内存的方法或推荐的优化方法

代码如下:

<?php

namespace App\Services;

use App\PropertyIntegration;
use GuzzleHttp\Client;
use App\Property;
use App\Integration;
use Carbon\Carbon;
use App\Exception;
use App\Transformation;
use App\Organization;
use Illuminate\Support\Arr;

class IntegrationService {
    private $_verbose;
    private $_client;
    private $_integration;
    private $_notifier;
    private $_config;
    private $_start_time;

/***************************************************************************************************
     1) First step - Gets data for Guzzle Client
****************************************************************************************************/
    public function firststep() {
        $organizations = Organization::where('org_status', 'Activo')->get();
        foreach ($organizations as $organization) {
            $megaagents = $organization->megaagents()->where('megaagent_status', 'Activo')
                                                        ->whereNotNull('megaagent_api_key')
                                                        ->get();
            $marketcenters = $organization->marketcenters()->where('mc_status', 'Activo')
                                                            ->whereNotNull('mc_api_key')
                                                            ->get();
            // PASS DATA TO GUZZLE                                              
            foreach ($megaagents as $megaagent) { 
                $this->initialize($megaagent, $ismegaagent = true);
                $this->execute($megaagent, $ismegaagent = true);
            }
            
            // PASS DATA TO GUZZLE
            foreach ($marketcenters as $marketcenter ) { 
                $this->initialize($marketcenter, $ismegaagent = false);
                $this->execute($marketcenter, $ismegaagent = false);
            }
        }
    }

/***************************************************************************************************
     2)   Send notification information in console verbose mode
****************************************************************************************************/

    private function notify($message, $type='info') {
        if($this->_verbose && $this->_notifier !== null) {
            $this->_notifier->{$type}($message);
        }
    }

/***************************************************************************************************
     3) Integrate Property API data with the Database
            Initialize integration service
            Fetch Properties from API Endpoint
            Insert/Update properties
****************************************************************************************************/

        public function execute ($record, $ismegaagent) {
          
            $properties = [];
            $query = [];
            if($ismegaagent) {
                $apikey = $record->megaagent_api_key;
                
            } else {
                $apikey = $record->mc_api_key;
            }
            
            $request = 'http://url .$apikey ;

            if($ismegaagent) {
                $this->notify('====================================================================================================');
                $this->notify('INITIALIZING INTEGRATION CREATE/UPDATE -> MEGA AGENT: ' . strtoupper($record->megaagent_name));
                $this->notify('====================================================================================================');
            } else {
                $this->notify('====================================================================================================');
                $this->notify('INITIALIZING INTEGRATION CREATE/UPDATE -> MARKET CENTER: ' . strtoupper($record->mc_name));
                $this->notify('====================================================================================================');
            }

        $response = [
            'int_properties_sent'      => 0,
            'int_properties_success'   => 0,
            'int_properties_updated'   => 0,
            'int_properties_failed'    => 0,
            'int_properties_ignored'   => 0
        ];
        
        // CREATES GUZZLE INSTANCE
        $this->_client = new Client([
            'base_uri' => $this->_config['base_uri']
            ]);

        $pageNumber = 0;
        $retry = 0;
        $next = true;

            while ($next) {
                try {
                    $this->notify('Fetching Properties For Page: ' . ++$pageNumber);
                    $data = null;
                    $data = $this->getProperties($request, $pageNumber);
                    if(is_array($data['objects'])) {
                        $this->notify('Processing Properties For Page: ' . $pageNumber);
                        $this->notify('TOTAL PROPERTIES: ' .$data['meta']['total_count']);
                        $totalproperties = count($data['objects']);
                        $this->notify('TOTAL PROPERTIES IN PAGE: ' .$totalproperties);

                        $result = $this->processProperties($data['objects'], $record, $ismegaagent);

                        $response['int_properties_sent'] += count($data['objects']);
                        $response['int_properties_success'] += $result['success'];
                        $response['int_properties_updated'] += $result['updated'];
                        $response['int_properties_ignored'] += $result['ignored'];
                        $response['int_properties_failed'] += $result['failed'];

                    }

                    $next = $data['meta']['next'];

                    if($next !== false) {
                        $request = 'url'.$next;

                    } else {
                        $this->notify('Last Page Proccesed: ' . $pageNumber);
                    }
                    $retry = 0;
                } catch (\Exception $ex) {
                    // Handle the exception
                    if($retry < 3) {
                        --$pageNumber;
                        $retry++;
                        $this->notify('Error fetching properties. Retrying...', 'error');
                        sleep(10);
                    } else {
                        $this->notify('Aborting Property Integration! Error: ' . $ex->getMessage(), 'error');
                        break;
                    }
                }
            }
            $this->notify('======================================================================================');

        $response['int_time_elapsed'] = $this->_start_time->diffInMinutes(Carbon::now());
        $this->_integration->fill($response)->save();
        $this->notify('Integration Completed: ' .
            $response['int_properties_success'] .
            ' Properties integrated successfully from ' .
            $response['int_properties_sent'] .
            ' sent');
        return $response;

        $this->notify('======================================================================================');
    }

 /***************************************************************************************************
     4)   Fetch property from the API Endpoint
****************************************************************************************************/

    private function getProperties($request, $pageNumber = 1) {
        $response = $this->_client->get($request, ['decode_content' => false]);
        echo 'Memory in use: ' . memory_get_usage() . ' ('. round(((memory_get_usage() / 1024) / 1024)) .'M)' . "\n";
        usleep(20000);
        if($response->getStatusCode() == 200) {
            $body = $response->getBody()->getContents();
            $data = json_decode($body, true);
          // return $data['objects'];
            return $data;

        } else {
            throw new \Exception($response->getReasonPhrase(), 1);
        }
    }

/***************************************************************************************************
     5)   Store property information in Database
             If property does not already exists in database then insert
                else if the property modification date is different update property
****************************************************************************************************/

    private function processProperties($properties, $record, $ismegaagent) {
        $dbPropertiesCollection = Property::get(['prop_id', 'updated_at']);
        $dbProperties = $dbPropertiesCollection->mapWithKeys(function ($item) {
            return [$item['prop_id'] => $item['updated_at']];
        })->toArray();

        $success = 0;
        $updated = 0;
        $failed = 0;
        $ignored = 0;
        
        foreach ($properties as $property) {
            try {
                if(!array_key_exists('KWT'.$property['id'], $dbProperties) && ($property['status'] == 3 || $property['status'] == 4 || $property['status'] == 2))  {
                    $inserted = Property::storeTokkoProperty($property, $record, $ismegaagent);
                    if($inserted) {
                        $this->notify('INSERT: Property ' . 'KWT'.$property['id'] . ' does not exists, Inserting Property');
                        $success++;
                    } else {
                        $this->notify('FAILED: Property ' . 'KWT'.$property['id'] . ' review expections');
                    }

                } elseif ($property['status'] == 3 || $property['status'] == 4 || $property['status'] == 2) {
                    $dbModification = Carbon::createFromFormat('Y-m-d H:i:s', $dbProperties['KWT'.$property['id']]);
                    $fechaModification = Carbon::createFromFormat('Y-m-d\TH:i:s', $property['deleted_at']);
                    
                    if($fechaModification->notEqualTo($dbModification)) {
                        $this->notify('UPDATE: Property ' . 'KWT'.$property['id'] . ' API informs last modification date ' .$fechaModification . ' and database last modification date is ' .$dbModification);
                        Property::updateTokkoProperty($property, $record, $ismegaagent);
                        $updated++;
                    } 
                    else {
                        $tagsUpdated = Property::reviewTokkoTags($property);
                        if($tagsUpdated) {
                            $this->notify('UPDATE: Property ' . 'KWT'.$property['id'] . ' Tags are different although modification date'  .$fechaModification . ' and database last modification date is ' .$dbModification);
                            $updated++;

                        } else {
                            $this->notify('IGNORE: Property ' . 'KWT'.$property['id'] . ' already exists with modification date in API '. $dbModification . ' and last API modification date is ' . $fechaModification);
                            $ignored++;
                        }
                        
                    } 
                } else {
                    $ignored++;
                }
                
            } catch (\Exception $ex) {
                // Handle the exception
                $failed++;
                // Store into integration errors
                $this->_integration->integrationerrors()->create([
                    'property_id' => 'KWT'.$property['id'],
                    'interror_error_message' => $ex->getMessage()
                ]);
                $this->notify('Error: Operation failed for Property # ' . 'KWT'.$property['id'] . '. Message: ' . $ex->getMessage(), 'error');
            }
        }

        return [
            'success'       => $success,
            'updated'       => $updated,
            'failed'        => $failed,
            'ignored'       => $ignored
        ];
    }

}