Повторяющиеся строки в базе данных при обновлении страницы laravel - PullRequest
1 голос
/ 01 апреля 2020

есть страница, которая обновляется каждые 5-7 секунд, и на ней обновляются записи из базы, но в моменты, когда эти записи дублируются, не подскажите, почему может быть эта ошибка?

- это модель ActiveCaller

namespace App;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class ActiveCaller extends Model
{
    protected $fillable = ['queue', 'employee_id', 'station', 'state', 'duration',
        'client_id', 'last_call'];

    public function Employee()
    {
        return $this->belongsTo(Employee::class);
    }

    /**
     * Convert duration attribute to acceptable format
     *
     * @param $value
     * @return string
     */
    public function getDurationAttribute($value)
    {
        if (empty($value))
            return $value;

        return $this->sec2hms($value);
    }

    public function getStateAttribute($value)
    {
        if (!empty($value))
            return trim($value);

        return null;
    }

    /**
     * Convert last call attribute to acceptable format
     *
     * @param $value
     * @return string
     */
    public function getLastCallAttribute($value)
    {
        $data = explode("\n", $value);

        $result = "";
        $i = 0;
        $len = count($data) - 1;

        foreach ($data as $item) {
            $item = str_replace("\r", "", $item);
            $delimiter = "</br>";
            if ($i == $len)
                $delimiter = "";

            if (empty($item) || (trim($item) == "No calls yet")) {
                $result .= "No calls yet$delimiter";
            } else {
                $result .= $this->sec2hms($item) . " min. ago $delimiter";
            }

            $i++;
        }

        return $result;
    }

    public function getStationAttribute($value)
    {
        return str_replace("\r\n", "</br>", $value);
    }

    private function sec2hms($sec, $padHours = FALSE)
    {
        $timeStart = Carbon::now();
        $timeEnd = Carbon::now()->addSeconds(intval($sec));

        return  $timeStart->diff($timeEnd)->format('%H:%I:%S');
    }
}

- это AmiApiController

class AmiApiController extends Controller
{
    public function fetchDashboardData()
    {
        $this->updateQueueState();

        $activeCallers = ActiveCaller::with('Employee')
            ->where('old', true)
            ->orderBy('queue')
            ->orderBy('employee_id')
            ->orderBy('station', 'asc')
            ->get();


        $waitingList = WaitingList::where('old', false)->get();
        $waitingList = $waitingList->unique('client_id');

        $charts = Chart::all()->toArray();

        $chartFormatData = [
            'Total' => [],
            'Callers' => [],
            'Queues' => [],
        ];

        foreach ($charts as $key => $chart) {
            $charts[$key]['data'] = json_decode($chart['data'], 1);
            $chartFormatData[$chart['name']]['total'] = 0;
            foreach ($charts[$key]['data']['statistic'] as $datum) {
//                if ($datum[0] === 'Effort')
//                    continue;

                $chartFormatData[$chart['name']]['label'][] = $datum[0];
                $chartFormatData[$chart['name']]['data'][] = $datum[1];
                $chartFormatData[$chart['name']]['name'] = $chart['name'];
            }
            $chartFormatData[$chart['name']]['total'] = array_sum($chartFormatData[$chart['name']]['data']);
//            $chartFormatData[$chart['name']]['label'] = array_reverse($chartFormatData[$chart['name']]['label']);
        }

        return response()->json([
            'activeCallers' => $activeCallers,
            'charts' => $chartFormatData,
            'waitingList' => $waitingList
        ], 200);
    }

Здесь мы начинаем проверять, можем ли мы обновить базу данных в это время

      /**
         * Check whether the database can be updated at this time
         *
         *  - Returns True if no updates are currently being made to the database
         *     and the latest update was less than 5 seconds later
         *  - 
Returns True if the update already occurs for more than 15 seconds
         *
         *  - Returns False if an update is already in the database
         *  - 
Returns False if the last update was within the last 5 seconds
         *
         *  If the parameter in $ json is passed true (by default)
         *  the method returns the answer in JSON format
         *
         *  If the parameter is passed false to $ json
         * method returns a php-shne Boolean value
         *
         * @param bool $json
         * @return bool|\Illuminate\Http\JsonResponse
         */
        public function canWeUpdate($json = true)
        {
            $result = ['return' => null, 'msg' => null];

            $isUpdating = Configuration::where('key', 'is_ami_data_updating')->first();

            if (is_null($isUpdating)) {
                Configuration::create(['key' => 'is_ami_data_updating', 'value' => 0]);
            }

            if ($isUpdating->value == true) {
                // if an update is currently in progress
                $checkingDate = Carbon::now()->addSeconds(-10);
                if ($isUpdating->updated_at < $checkingDate) {
                    // if the update is longer than 15 seconds, we will cancel this update
                    $isUpdating->update(['value' => false]);
                    $result['return'] = true;
                    $result['msg'] = "Old update in database";
                } else {
                    // if the update is less than 15 seconds, we cannot update again
                    $result['return'] = false;
                    $result['msg'] = "CURRENTLY UPDATE";
                }
            } else if ($isUpdating->updated_at > Carbon::now()->addSeconds(-3)) {
                // if the last update was less than 5 seconds ago, we cannot update
                $result['return'] = false;
                $result['msg'] = "TOO EARLY";
            } else {
                //if the last update was more than 5 seconds ago, we allow the update
                $result['return'] = true;
                $result['msg'] = "OK";
            }

            if ($json)
                return $this->simpleResponse($result['return'], $result['msg']);

            return $result['return'];
        }

- это метод проверки наличия новых данных в базе данных

        /**
         * A method to check if new data is in the database
         *
         * Returns True if validation time is less than database update time
         * Returns False if validation time is longer than database update time
         * Returns False if there is no data in the database
         *
         * @param \Illuminate\Http\Request $request
         * @return \Illuminate\Http\JsonResponse
         */
        public function checkForNewData(Request $request)
        {
            $date = new Carbon($request->last_call);
            $lastRecord = ActiveCaller::latest()->first();

            if (is_null($lastRecord))
                return $this->simpleResponse(false);

            if ($date < $lastRecord->updated_at) {
                return $this->simpleResponse(true);
            } else
                return $this->simpleResponse(false);
        }

        /**
         * Method for loading table data
         *
         * Agents - information about active numbers in the PBX in all queues
         * Waiting - information about numbers in standby mode
         *
         * @return \Illuminate\Http\JsonResponse
         */
        public function renderAgentTable()
        {
            $agents = ActiveCaller::with('Employee')
                ->where('old', true)
                ->orderBy('queue')
                ->orderBy('station', 'asc')
                ->get();

            $waitingList = WaitingList::all();

            $agentsTable = View::make('dashboard.render.agent-table', ['agents' => $agents]);
            $waitingTable = View::make('dashboard.render.waiting-list-table', ['waitingList' => $waitingList]);

            $result =
                [
                    'agents' => $agentsTable->render(),
                    'waiting' => $waitingTable->render(),
                ];

            $result = array_merge($result, $this->renderDashboardChart(new Request()));

            return response()->json($result);
        }

        /**
         * Method for updating data from AMI
         *
         * updating data for ActiveCaller
         * updating data for WaitingList
         */
        public function updateQueueState()
        {
            if (!$this->canWeUpdate(false)) {
    //            dd("We can't update (large check)");
                return;
            }

            $lastUpdateTime = ActiveCaller::latest()->first();

            if ($lastUpdateTime != null)
                if ($lastUpdateTime->created_at > Carbon::now()->addSeconds(-3)) {
    //                dd("We can't update (small check)");
                    return;
                }

            // we notice the launch of the update in the database
            $isAmiDataUpdating = Configuration::where('key', 'is_ami_data_updating')->first();
            $isAmiDataUpdating->update(['value' => true]);

            $this->ClearOldRecords();

            $queues = Queue::where('on_dashboard', '=', '1')->get()->toArray();
            // we go through all the queues that are available in AMI
            foreach ($queues as $queue) {
                $command = new AMIQueueMemberState($queue['name']);

                // we get a list of numbers and a waiting list of calls
                $response = $command->handle();
                $agents = $response['agents'];
                $callers = $response['callers'];

                //convert the waiting list to PeerList
                $peerList = PeerInfo::hydrate($agents);
                $employees = new Collection();

                foreach ($callers as $caller) {
                    $caller['queue'] = $queue['name'];
                    WaitingList::create($caller);
                }

                $peerList->each(function (PeerInfo $peer) use ($employees) {
                    $record = Record
                        ::where('phone', 'like', '%' . $peer->name . '%')
                        ->where('end_date', null)
                        ->get()->first();

                    $data = null;
                    if ($record != null) {
                        // check if this user already has an entry in active_callers (not old)
                        $active = ActiveCaller
                            ::where('employee_id', $record['employee_id'])
                            ->where('old', false)
                            ->get()->first();

                        // if so, add him another number and
                        // we move on to the next iteration
                        if ($active != null) {

                           if ($this->HandleSingleActive($active, $peer->name, $peer->last_call))

                                return;
                        }


                        $peer->station = $record['station_name'];
                        $peer->employee_id = $record['employee_id'];

                        $a = collect($peer->toArray());
                        $data = $a->except(['name', 'pause'])->toArray();
                        $data['station'] = "$peer->station | $peer->name";
                    } else {
                        $peer->station = "- | $peer->name";
                        $a = collect($peer->toArray());
                        $data = $a->except(['name', 'pause'])->toArray();
                    }
                    ActiveCaller::create($data);
                });
            }

            $this->updateDashboardChart();

            $isAmiDataUpdating->update(['value' => false]);
        }

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...