作者 李美松

v6优化程序 统计数据任务优化

<?php
namespace App\Console\Commands\GeneratePDF;
use App\Models\File\PdfFile;
use App\Models\ProjectAssociation\ProjectAssociation;
use App\Services\CosService;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Console\Command;
class GeneratePdfData extends Command
{
// use CmdSignal;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'generate_pdf_data';
/**
* The console command description.
*
* @var string
*/
protected $description = '生成v6绑定的aicc用户的pdf备用数据';
// 最大支持5个进程
public $maxRunNumber = 50;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
public function handle()
{
return $this->main();
}
/**
* @return int
*/
public function start(): int
{
return $this->main();
}
/**
* @return int
*/
protected function main()
{
$month = date('m');
$list = ProjectAssociation::query()->whereStatus(ProjectAssociation::STATUS_NORMAL)
->where('m_status', '!=', $month)->first();
if (is_null($list)) {
$this->error('没有任务,等待中');
sleep(60);
return 0;
}
$pdfFile = new PdfFile();
$bool = $pdfFile->saveData(['pid' => $list->id]);
if (!$bool) {
$this->error('生成v6绑定的aicc用户的pdf备用数据添加失败');
return 0;
}
$list->m_status = $month;
$list->save();
$this->info('生成v6绑定的aicc用户的pdf备用数据添加成功');
return 0;
}
}
... ...
<?php
namespace App\Console\Commands;
namespace App\Console\Commands\GeneratePDF;
use App\Http\Controllers\File\FileController;
use App\Models\File\DataFile;
use App\Models\File\PdfFile;
use App\Models\ProjectAssociation\ProjectAssociation;
use App\Services\CosService;
use Barryvdh\DomPDF\Facade\Pdf;
... ... @@ -12,7 +11,7 @@ use Illuminate\Http\File;
class ProjectFilePDF extends Command
{
use CmdSignal;
// use CmdSignal;
/**
* The name and signature of the console command.
... ... @@ -28,14 +27,8 @@ class ProjectFilePDF extends Command
*/
protected $description = '网站项目数据,生成PDF文件';
protected $ProjectAssociation;
protected $DataFile;
protected $time;
protected $fileController;
protected $CosService;
// 最大支持5个进程
... ... @@ -48,71 +41,89 @@ class ProjectFilePDF extends Command
*/
public function __construct()
{
$this->ProjectAssociation = new ProjectAssociation();
$this->DataFile = new DataFile();
$this->time = date("Y-m");
$this->fileController = new FileController();
$this->CosService = new CosService();
parent::__construct();
}
// public function handle()
// {
// $project_data = [];
// $html = $this->html($project_data);
// $filename = hash('md5', $this->time . '-' . '$project_id' . '-' . '$friend_id' . '-' . '$user_id');
// $this->savePDF($html, $filename);
//// $this->testStreamPdf($html, $filename);
//// $file_path = $this->savePDF2($html, $filename);
// return 0;
// }
public function handle()
{
// 开始时间
$startTime = microtime(true);
$html = $this->html([]);
$filename = hash('md5', $this->time . '-' . random_int(100000, 999999));
$this->savePDF($html, $filename);
// 结束时间
$endTime = microtime(true);
// 计算执行时间
$executionTime = ($endTime - $startTime);
// 输出执行时间
var_dump("程序执行时间: " . $executionTime . " 秒");
// return $this->main();
}
/**
* @return int
*/
public function start(): int
{
# 0 - 未生成
# 1 - 已生成
# 2 - 其它问题
$is_pdf = 0;
$lists = $this->ProjectAssociation::query()->where('is_pdf', $is_pdf)
->where('project_id', '!=', 0)
->where('friend_id', '!=', 0)
->where('user_id', '!=', 0)
->where('created_at', 'like', $this->time . '%')->first();
if (is_null($lists)) {
$this->debug_echo('没有任务,等待中');
sleep(30);
return $this->main();
}
/**
* @return int
*/
protected function main()
{
$list = PdfFile::query()->whereIsPdf(PdfFile::GENERATE_NOT_PDF)->first();
if (is_null($list)) {
$this->error('没有任务,等待中');
sleep(60);
return 0;
}
$pid = $list->pid;
if (empty($pid)) {
$this->error('数据错误');
return 0;
}
$isExists = ProjectAssociation::query()->whereId($pid)->whereStatus(ProjectAssociation::STATUS_NORMAL)->first();
if (is_null($isExists)) {
$this->error('数据已被禁用 —— ' . $pid);
return 0;
}
$key = $this->signature . '-' . $lists->id;
$count = redis_get($key);
$project_id = $lists->project_id;
$user_id = $lists->user_id;
$friend_id = $lists->friend_id;
$key = 'generate_pdf_' . $list->id;
$count = (int)redis_get($key) ?: 0;
$project_id = $isExists->project_id;
$user_id = $isExists->user_id;
$friend_id = $isExists->friend_id;
// todo 根据项目查询数据
$project_data = [];
$html = $this->html($project_data);
$filename = hash('md5', $this->time . '-' . $project_id . '-' . $friend_id . '-' . $user_id);
$file_path = $this->savePDF($html, $filename);
if (empty($file_path)) {
$this->debug_echo('pdf生成失败!');
if ($count == 2) {
$list->is_pdf = PdfFile::GENERATE_OTHER_PDF;
$list->save();
$this->error('项目文件数据保存失败! - 其他原因 - ' . $key);
return 0;
}
$isRes = $this->DataFile->saveData(compact('project_id', 'user_id', 'friend_id', 'file_path') + ['time' => $this->time]);
if (!$isRes) {
if ($count == 2) {
$lists->is_pdf = 2;
$lists->save();
$this->debug_echo('项目文件数据保存失败! - 其他原因 - ' . $key);
} else {
$file_path = $this->savePDF($html, $filename);
if (empty($file_path)) {
redis_set($key, $count + 1);
$this->debug_echo('项目文件数据保存失败! - ' . $key);
}
$this->error('pdf生成失败!');
return 0;
}
$lists->is_pdf = 1;
$lists->save();
// 保存文件路径
$list->file_path = $file_path;
$list->is_pdf = PdfFile::GENERATE_PDF;
$list->save();
$this->info('项目文件数据保存成功!');
return 0;
}
... ... @@ -131,18 +142,22 @@ class ProjectFilePDF extends Command
}
// 指定保存路径和文件名
$savePath = $pdf_path . $filename . '.pdf';
if (file_exists($savePath)) {
echo '文件已经存在';
return 0;
}
$path = '/PDF/' . $this->time;
$pdf = PDF::loadHTML($html);
$pdf->save($savePath);
$path = '/V6/PDF/' . $this->time;
// 创建一个文件实例
$file = new File($savePath);
return $this->CosService->uploadFile($file, $path, $filename . '.pdf');
// 获取二进制文件
$binary = $pdf->output(['compres' => 0]);
// 将文件保存到本地
// $pdf->save($savePath);
// $binary = new File($savePath);
return $this->CosService->uploadFile($binary, $path, $filename . '.pdf');
}
/**
... ... @@ -153,6 +168,6 @@ class ProjectFilePDF extends Command
protected function html($item)
{
$font_path = storage_path('fonts\msyh.ttf');
return '<html><head><title>Laravel</title><meta http-equiv=\'Content-Type\' content=\'text/html; charset=utf-8\'/><style>body{ font-family: \'msyh\'; } @font-face { font-family: \'msyh\'; font-style: normal; font-weight: normal; src: url(' . $font_path . ') format(\'truetype\'); }</style></head><body><div class=\'container\'><div class=\'content\'><p style=\'font-family: msyh, DejaVu Sans,sans-serif;\'>献给母亲的爱</p><div style=\'font-family: msyh, DejaVu Sans,sans-serif;\' class=\'title\'>Laravel 5中文测试</div><div class=\'title\'>测试三askjdhfkjasdhf</div></div></div></body></html>';
return '<html><head><title>Laravel</title><meta http-equiv=\'Content-Type\' content=\'text/html; charset=utf-8\'/><style>body{ font-family: \'msyh\'; } @font-face { font-family: \'msyh\'; font-style: normal; font-weight: normal; src: url(' . $font_path . ') format(\'truetype\'); }</style></head><body><div class=\'container\'><div class=\'content\'><p style=\'font-family: msyh, DejaVu Sans,sans-serif;\'>献给母亲的爱</p><div style=\'font-family: msyh, DejaVu Sans,sans-serif;\' class=\'title\'>Laravel 5中文测试sdsd</div><div class=\'title\'>测试三askjdhfkjasdhf</div></div></div></body></html>';
}
}
... ...
<?php
namespace App\Console\Commands;
namespace App\Console\Commands\GeneratePDF;
use App\Models\File\DataFile;
use App\Models\File\PdfFile;
use App\Models\ProjectAssociation\ProjectAssociation;
use Illuminate\Console\Command;
class WebsiteData extends Command
class PushAiccData extends Command
{
use CmdSignal;
// use CmdSignal;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'website_data';
protected $signature = 'push_data_to_aicc';
/**
* The console command description.
... ... @@ -39,41 +40,65 @@ class WebsiteData extends Command
parent::__construct();
}
public function handle()
{
return $this->main();
}
public function start(): int
{
# 0 - 未推送
# 1 - 已推送
# 2 - 其他问题
$status = 0;
$lists = DataFile::query()->where('status', $status)
->where('created_at', 'like', $this->time . '%')->first();
if (is_null($lists)) {
$this->debug_echo('没有任务,等待中');
sleep(30);
return $this->main();
}
protected function main()
{
$list = PdfFile::query()->whereIsPdf(PdfFile::GENERATE_PUSH)->whereIsPush(PdfFile::GENERATE_NOT_PUSH)->first();
if (is_null($list)) {
$this->error('向AICC推送 - 没有任务,等待中');
sleep(60);
return 0;
}
$key = $this->signature . '-' . $lists->id;
$count = redis_get($key);
$data = $lists;
$pid = $list->pid;
if (empty($pid)) {
$this->error('向AICC推送数据错误');
return 0;
}
$isExists = ProjectAssociation::query()->whereId($pid)->whereStatus(ProjectAssociation::STATUS_NORMAL)->first();
if (is_null($isExists)) {
$this->error('向AICC推送数据已被禁用 —— ' . $pid);
return 0;
}
$key = 'push_data_to_aicc_' . $list->id;
$count = (int)redis_get($key) ?: 0;
$data = $list->toArray();
$data['project_id'] = $isExists->project_id;
$data['friend_id'] = $isExists->friend_id;
$data['user_id'] = $isExists->user_id;
$url = env('AICC_URL');
$msg = http_post($url, json_encode(compact('data')));
$status_code = 0;
if ($msg) {
$status_code = (int)$msg['status'];
}
if ($status_code != 200) {
if ($count == 2) {
$lists->status = 2;
$lists->save();
$list->is_push = PdfFile::GENERATE_OTHER_PUSH;
$list->save();
$this->debug_echo('项目文件数据保存失败! - 其他原因 - ' . $key);
} else {
return 0;
}
if ($status_code != 200) {
redis_set($key, $count + 1);
$this->debug_echo('项目文件数据保存失败! - ' . $key);
return 0;
}
}
$lists->status = 1;
$lists->save();
$list->is_push = PdfFile::GENERATE_PUSH;
$list->save();
$this->info('项目文件数据保存成功!');
return 0;
}
... ...
<?php
namespace App\Models\File;
use App\Models\Base;
class DataFile extends Base
{
protected $table = 'gl_data_file';
public function saveData(array $data): bool
{
# v6项目ID
$project_id = (int)$data['project_id'] ?? 0;
$isRes = self::query()->where('project_id', $project_id)->where('created_at', 'like', $data['time'] . '%')->first();
if (!$isRes) {
$isRes = new self();
$isRes->project_id = $project_id;
# AICC用户ID
$isRes->user_id = $data['user_id'];
# 第三方朋友ID
$isRes->friend_id = $data['friend_id'];
# 生成文件路径
$isRes->file_path = $data['file_path'];
}
return $isRes->save();
}
/**
* @param int $page
* @param int $perPage
* @return array
*/
public function allData(int $page = 1, int $perPage = 15)
{
$lists = self::query()->paginate($perPage, ['*'], 'page', $page);
$items = $lists->Items();
$totalPage = $lists->lastPage();
$total = $lists->total();
$currentPage = $lists->currentPage();
return compact('total', 'items', 'totalPage', 'currentPage');
}
}
<?php
namespace App\Models\File;
use App\Models\Base;
/**
* App\Models\File\PdfFile
*
* @property int $id
* @property int $pid AICC用户ID
* @property string $file_path 生成文件路径
* @property int $is_pdf 0 - 未生成 1 - 已生成 2 - 其它问题
* @property int|null $is_push 0 - 未推送 1 - 已推送 2 - 其他问题
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method \Illuminate\Database\Eloquent\Builder|PdfFile newModelQuery()
* @method \Illuminate\Database\Eloquent\Builder|PdfFile newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|PdfFile query()
* @method \Illuminate\Database\Eloquent\Builder|PdfFile whereCreatedAt($value)
* @method \Illuminate\Database\Eloquent\Builder|PdfFile whereFilePath($value)
* @method \Illuminate\Database\Eloquent\Builder|PdfFile whereId($value)
* @method \Illuminate\Database\Eloquent\Builder|PdfFile whereIsPdf($value)
* @method \Illuminate\Database\Eloquent\Builder|PdfFile whereIsPush($value)
* @method \Illuminate\Database\Eloquent\Builder|PdfFile wherePid($value)
* @method \Illuminate\Database\Eloquent\Builder|PdfFile whereUpdatedAt($value)
* @mixin \Eloquent
*/
class PdfFile extends Base
{
protected $table = 'gl_pdf_file';
/** @var int PDF - 未生成 */
const GENERATE_NOT_PDF = 0;
/** @var int PDF - 已生成 */
const GENERATE_PDF = 1;
/** @var int PDF - 其它问题 */
const GENERATE_OTHER_PDF = 2;
/** @var int AICC - 未推送 */
const GENERATE_NOT_PUSH = 0;
/** @var int AICC - 已推送 */
const GENERATE_PUSH = 1;
/** @var int AICC - 其他问题 */
const GENERATE_OTHER_PUSH = 2;
public function saveData(array $data): bool
{
# v6项目ID
$pid = (int)$data['pid'] ?? 0;
$time = $data['time'] ?? date('Y-m-d');
$isRes = self::query()->wherePid($pid)->where('created_at', 'like', $time . '%')->first();
if (!$isRes) {
$isRes = new self();
$isRes->pid = $pid;
# 生成文件路径
$isRes->file_path = $data['file_path'] ?? '';
}
return $isRes->save();
}
}
... ...
... ... @@ -5,10 +5,47 @@ namespace App\Models\ProjectAssociation;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
* App\Models\ProjectAssociation\ProjectAssociation
*
* @property int $id
* @property int $project_id V6项目ID
* @property int $friend_id AICC朋友ID
* @property int $user_id AICC用户ID
* @property string|null $nickname AICC朋友昵称
* @property string|null $user_name AICC用户姓名
* @property string|null $image AICC朋友头像
* @property int|null $status 1 - 正常, 0 - 禁用
* @property int|null $m_status 统计当月是否生成数据
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method Builder|ProjectAssociation newModelQuery()
* @method Builder|ProjectAssociation newQuery()
* @method static Builder|ProjectAssociation query()
* @method Builder|ProjectAssociation whereCreatedAt($value)
* @method Builder|ProjectAssociation whereFriendId($value)
* @method Builder|ProjectAssociation whereId($value)
* @method Builder|ProjectAssociation whereImage($value)
* @method Builder|ProjectAssociation whereMStatus($value)
* @method Builder|ProjectAssociation whereNickname($value)
* @method Builder|ProjectAssociation whereProjectId($value)
* @method Builder|ProjectAssociation whereStatus($value)
* @method Builder|ProjectAssociation whereUpdatedAt($value)
* @method Builder|ProjectAssociation whereUserId($value)
* @method Builder|ProjectAssociation whereUserName($value)
* @mixin \Eloquent
*/
class ProjectAssociation extends Model
{
protected $table = 'gl_project_association';
/** @var int 数据状态 - 正常 */
const STATUS_NORMAL = 1;
/** @var int 数据状态 - 禁用 */
const STATUS_DISABLED = 0;
/**
* 保存|修改数据
* @param array $data
... ...
... ... @@ -35,7 +35,8 @@ class CosService
$cosClient->putObject([
'Bucket' => $cos['bucket'],
'Key' => $key,
'Body' => fopen($files->getRealPath(), 'r'),
// 'Body' => fopen($files->getRealPath(), 'r'),
'Body' => $files,
]);
return $key;
}
... ...
... ... @@ -23,6 +23,7 @@
"swooletw/laravel-swoole": "^2.13"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.13",
"facade/ignition": "^2.5",
"fakerphp/faker": "^1.9.1",
"laravel/sail": "^1.0.1",
... ...