Compare commits
11 Commits
ddc6310331
...
35761327f9
| Author | SHA1 | Date |
|---|---|---|
|
|
35761327f9 | 3 years ago |
|
|
abdebd3c9a | 3 years ago |
|
|
75c728d6bd | 3 years ago |
|
|
1158a040fa | 3 years ago |
|
|
1ab66350a7 | 3 years ago |
|
|
f64540e648 | 3 years ago |
|
|
159e0d36d5 | 3 years ago |
|
|
68b136d3a1 | 3 years ago |
|
|
51c4ea1903 | 3 years ago |
|
|
7dab42469c | 3 years ago |
|
|
cfadd01356 | 3 years ago |
@ -0,0 +1,27 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Enums; |
||||||
|
|
||||||
|
use App\Services\Chunkers\JsonChunker; |
||||||
|
use App\Services\Converters\JsonToDatabaseConverter; |
||||||
|
|
||||||
|
enum FileFormatEnum: string |
||||||
|
{ |
||||||
|
case JSON = 'json'; |
||||||
|
|
||||||
|
public function chunker(string $uuid, string $path): \Generator |
||||||
|
{ |
||||||
|
$chunker = match ($this) { |
||||||
|
self::JSON => new JsonChunker |
||||||
|
}; |
||||||
|
|
||||||
|
return $chunker->handle($uuid, $path); |
||||||
|
} |
||||||
|
|
||||||
|
public function converter() |
||||||
|
{ |
||||||
|
return match($this){ |
||||||
|
self::JSON => new JsonToDatabaseConverter |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Http\Controllers\V1; |
||||||
|
|
||||||
|
use App\Enums\FileFormatEnum; |
||||||
|
use App\Http\Controllers\Controller; |
||||||
|
use App\Jobs\ChunkFile; |
||||||
|
use Illuminate\Http\Request; |
||||||
|
use Illuminate\Support\Facades\Redis; |
||||||
|
use Illuminate\Support\Facades\Storage; |
||||||
|
use Illuminate\Support\Str; |
||||||
|
|
||||||
|
class ConvertController extends Controller |
||||||
|
{ |
||||||
|
public function convert(FileFormatEnum $format, Request $request) |
||||||
|
{ |
||||||
|
Storage::put( |
||||||
|
$request->file('file')->getClientOriginalName(), |
||||||
|
$request->file('file')->getContent(), |
||||||
|
); |
||||||
|
|
||||||
|
ChunkFile::dispatch( |
||||||
|
Str::uuid(), |
||||||
|
$request->file('file')->getClientOriginalName(), |
||||||
|
$format |
||||||
|
); |
||||||
|
|
||||||
|
return response([ |
||||||
|
'msg' => 'done', |
||||||
|
'success' => true |
||||||
|
]); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,8 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Interfaces; |
||||||
|
|
||||||
|
interface ChunkerInterface |
||||||
|
{ |
||||||
|
public function handle(string $uuid, string $path): \Generator; |
||||||
|
} |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Jobs; |
||||||
|
|
||||||
|
use App\Enums\FileFormatEnum; |
||||||
|
use Illuminate\Bus\Queueable; |
||||||
|
use Illuminate\Contracts\Queue\ShouldBeUnique; |
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue; |
||||||
|
use Illuminate\Foundation\Bus\Dispatchable; |
||||||
|
use Illuminate\Queue\InteractsWithQueue; |
||||||
|
use Illuminate\Queue\SerializesModels; |
||||||
|
use Illuminate\Support\Facades\Redis; |
||||||
|
use Illuminate\Support\Facades\Storage; |
||||||
|
|
||||||
|
class ChunkFile implements ShouldQueue |
||||||
|
{ |
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new job instance. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
*/ |
||||||
|
public function __construct( |
||||||
|
public string $uuid, |
||||||
|
public string $path, |
||||||
|
public FileFormatEnum $format |
||||||
|
) |
||||||
|
{ |
||||||
|
// |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the job. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
*/ |
||||||
|
public function handle() |
||||||
|
{ |
||||||
|
$chunks = $this->format->chunker($this->uuid, $this->path); |
||||||
|
foreach ($chunks as $key => $chunk) { |
||||||
|
StoreChunk::dispatch($chunk); |
||||||
|
Redis::set($this->uuid . ":latest", $key); |
||||||
|
} |
||||||
|
Storage::delete($this->path); |
||||||
|
Redis::del($this->uuid . ":latest"); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,76 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Jobs; |
||||||
|
|
||||||
|
use App\Models\User; |
||||||
|
use App\Pipes\StoreChunk\AgeFilterPipe; |
||||||
|
use App\Pipes\StoreChunk\CreditCardFilter; |
||||||
|
use Illuminate\Bus\Queueable; |
||||||
|
use Illuminate\Contracts\Queue\ShouldBeUnique; |
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue; |
||||||
|
use Illuminate\Foundation\Bus\Dispatchable; |
||||||
|
use Illuminate\Pipeline\Pipeline; |
||||||
|
use Illuminate\Queue\InteractsWithQueue; |
||||||
|
use Illuminate\Queue\SerializesModels; |
||||||
|
use Illuminate\Support\Carbon; |
||||||
|
use Illuminate\Support\Collection; |
||||||
|
|
||||||
|
class StoreChunk implements ShouldQueue |
||||||
|
{ |
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; |
||||||
|
|
||||||
|
public Collection $chunk; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new job instance. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
*/ |
||||||
|
public function __construct( |
||||||
|
array $chunk |
||||||
|
) |
||||||
|
{ |
||||||
|
$this->chunk = collect($chunk); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the job. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
*/ |
||||||
|
public function handle() |
||||||
|
{ |
||||||
|
$chunk = (new Pipeline(app())) |
||||||
|
->through([ |
||||||
|
AgeFilterPipe::class, |
||||||
|
CreditCardFilter::class, |
||||||
|
]) |
||||||
|
->send($this->changeDateOfBirthToCarbon()) |
||||||
|
->thenReturn(); |
||||||
|
|
||||||
|
User::insert( |
||||||
|
$this->prepare($chunk)->toArray() |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
protected function changeDateOfBirthToCarbon() |
||||||
|
{ |
||||||
|
return $this->chunk->map(function ($item) { |
||||||
|
if (!strpos($item['date_of_birth'], '/')) { |
||||||
|
$item['date_of_birth'] = Carbon::create($item['date_of_birth']); |
||||||
|
} else { |
||||||
|
$item['date_of_birth'] = Carbon::createFromFormat('d/m/Y', $item['date_of_birth']); |
||||||
|
} |
||||||
|
|
||||||
|
return $item; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
protected function prepare($chunk) |
||||||
|
{ |
||||||
|
return $chunk->map(function ($item) { |
||||||
|
$item['credit_card'] = json_encode($item['credit_card']); |
||||||
|
return $item; |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Pipes\StoreChunk; |
||||||
|
|
||||||
|
use Illuminate\Support\Carbon; |
||||||
|
use Illuminate\Support\Collection; |
||||||
|
|
||||||
|
class AgeFilterPipe |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @param Collection $chunk |
||||||
|
* @param \Closure $next |
||||||
|
* @return mixed |
||||||
|
*/ |
||||||
|
public function handle($chunk, \Closure $next) |
||||||
|
{ |
||||||
|
$chunk = $chunk->filter(function ($item) { |
||||||
|
$age = $item['date_of_birth']->age; |
||||||
|
return 18 <= $age && $age <= 65; |
||||||
|
}); |
||||||
|
|
||||||
|
return $next($chunk); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Pipes\StoreChunk; |
||||||
|
|
||||||
|
use Illuminate\Support\Collection; |
||||||
|
|
||||||
|
class CreditCardFilter |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @param Collection $chunk |
||||||
|
* @param \Closure $next |
||||||
|
* @return mixed |
||||||
|
*/ |
||||||
|
public function handle($chunk, \Closure $next) |
||||||
|
{ |
||||||
|
// filter based on credit card number |
||||||
|
|
||||||
|
return $next($chunk); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Providers; |
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Gate; |
||||||
|
use Laravel\Horizon\Horizon; |
||||||
|
use Laravel\Horizon\HorizonApplicationServiceProvider; |
||||||
|
|
||||||
|
class HorizonServiceProvider extends HorizonApplicationServiceProvider |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Bootstrap any application services. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
*/ |
||||||
|
public function boot() |
||||||
|
{ |
||||||
|
parent::boot(); |
||||||
|
|
||||||
|
// Horizon::routeSmsNotificationsTo('15556667777'); |
||||||
|
// Horizon::routeMailNotificationsTo('example@example.com'); |
||||||
|
// Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel'); |
||||||
|
|
||||||
|
// Horizon::night(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Register the Horizon gate. |
||||||
|
* |
||||||
|
* This gate determines who can access Horizon in non-local environments. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
*/ |
||||||
|
protected function gate() |
||||||
|
{ |
||||||
|
Gate::define('viewHorizon', function ($user) { |
||||||
|
return in_array($user->email, [ |
||||||
|
// |
||||||
|
]); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Services\Chunkers; |
||||||
|
|
||||||
|
use App\Interfaces\ChunkerInterface; |
||||||
|
use App\Services\Decoder\JsonDecoder; |
||||||
|
use Illuminate\Support\Facades\Redis; |
||||||
|
use Illuminate\Support\Facades\Storage; |
||||||
|
use JsonMachine\Exception\InvalidArgumentException; |
||||||
|
use JsonMachine\Items; |
||||||
|
use JsonMachine\JsonDecoder\ExtJsonDecoder; |
||||||
|
|
||||||
|
class JsonChunker implements ChunkerInterface |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @throws InvalidArgumentException |
||||||
|
*/ |
||||||
|
public function handle(string $uuid, string $path): \Generator |
||||||
|
{ |
||||||
|
$chunk = []; |
||||||
|
|
||||||
|
$latest = Redis::get($uuid . ":latest") ?? 0; |
||||||
|
|
||||||
|
foreach (Items::fromFile(Storage::path($path), ['decoder' => new ExtJsonDecoder(true)]) as $key => $value) { |
||||||
|
if ($key < $latest) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// for cut off test you have to uncomment below codes |
||||||
|
// if($key == 900){ |
||||||
|
// throw new \Exception('cut off'); |
||||||
|
// } |
||||||
|
|
||||||
|
$chunk[] = $value; |
||||||
|
|
||||||
|
if (count($chunk) == 500) { |
||||||
|
yield $key => $chunk; |
||||||
|
$chunk = []; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (count($chunk) > 0) { |
||||||
|
yield $key => $chunk; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,197 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use Illuminate\Support\Str; |
||||||
|
|
||||||
|
return [ |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Horizon Domain |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| This is the subdomain where Horizon will be accessible from. If this |
||||||
|
| setting is null, Horizon will reside under the same domain as the |
||||||
|
| application. Otherwise, this value will serve as the subdomain. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'domain' => env('HORIZON_DOMAIN'), |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Horizon Path |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| This is the URI path where Horizon will be accessible from. Feel free |
||||||
|
| to change this path to anything you like. Note that the URI will not |
||||||
|
| affect the paths of its internal API that aren't exposed to users. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'path' => env('HORIZON_PATH', 'horizon'), |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Horizon Redis Connection |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| This is the name of the Redis connection where Horizon will store the |
||||||
|
| meta information required for it to function. It includes the list |
||||||
|
| of supervisors, failed jobs, job metrics, and other information. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'use' => 'default', |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Horizon Redis Prefix |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| This prefix will be used when storing all Horizon data in Redis. You |
||||||
|
| may modify the prefix when you are running multiple installations |
||||||
|
| of Horizon on the same server so that they don't have problems. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'prefix' => env( |
||||||
|
'HORIZON_PREFIX', |
||||||
|
Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' |
||||||
|
), |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Horizon Route Middleware |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| These middleware will get attached onto each Horizon route, giving you |
||||||
|
| the chance to add your own middleware to this list or change any of |
||||||
|
| the existing middleware. Or, you can simply stick with this list. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'middleware' => ['web'], |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Queue Wait Time Thresholds |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| This option allows you to configure when the LongWaitDetected event |
||||||
|
| will be fired. Every connection / queue combination may have its |
||||||
|
| own, unique threshold (in seconds) before this event is fired. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'waits' => [ |
||||||
|
'redis:default' => 60, |
||||||
|
], |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Job Trimming Times |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| Here you can configure for how long (in minutes) you desire Horizon to |
||||||
|
| persist the recent and failed jobs. Typically, recent jobs are kept |
||||||
|
| for one hour while all failed jobs are stored for an entire week. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'trim' => [ |
||||||
|
'recent' => 60, |
||||||
|
'pending' => 60, |
||||||
|
'completed' => 60, |
||||||
|
'recent_failed' => 10080, |
||||||
|
'failed' => 10080, |
||||||
|
'monitored' => 10080, |
||||||
|
], |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Metrics |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| Here you can configure how many snapshots should be kept to display in |
||||||
|
| the metrics graph. This will get used in combination with Horizon's |
||||||
|
| `horizon:snapshot` schedule to define how long to retain metrics. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'metrics' => [ |
||||||
|
'trim_snapshots' => [ |
||||||
|
'job' => 24, |
||||||
|
'queue' => 24, |
||||||
|
], |
||||||
|
], |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Fast Termination |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| When this option is enabled, Horizon's "terminate" command will not |
||||||
|
| wait on all of the workers to terminate unless the --wait option |
||||||
|
| is provided. Fast termination can shorten deployment delay by |
||||||
|
| allowing a new instance of Horizon to start while the last |
||||||
|
| instance will continue to terminate each of its workers. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'fast_termination' => false, |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Memory Limit (MB) |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| This value describes the maximum amount of memory the Horizon master |
||||||
|
| supervisor may consume before it is terminated and restarted. For |
||||||
|
| configuring these limits on your workers, see the next section. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'memory_limit' => 64, |
||||||
|
|
||||||
|
/* |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| Queue Worker Configuration |
||||||
|
|-------------------------------------------------------------------------- |
||||||
|
| |
||||||
|
| Here you may define the queue worker settings used by your application |
||||||
|
| in all environments. These supervisors and settings handle all your |
||||||
|
| queued jobs and will be provisioned by Horizon during deployment. |
||||||
|
| |
||||||
|
*/ |
||||||
|
|
||||||
|
'defaults' => [ |
||||||
|
'supervisor-1' => [ |
||||||
|
'connection' => 'redis', |
||||||
|
'queue' => ['default'], |
||||||
|
'balance' => 'auto', |
||||||
|
'maxProcesses' => 1, |
||||||
|
'maxTime' => 0, |
||||||
|
'maxJobs' => 0, |
||||||
|
'memory' => 128, |
||||||
|
'tries' => 1, |
||||||
|
'timeout' => 60, |
||||||
|
'nice' => 0, |
||||||
|
], |
||||||
|
], |
||||||
|
|
||||||
|
'environments' => [ |
||||||
|
'production' => [ |
||||||
|
'supervisor-1' => [ |
||||||
|
'maxProcesses' => 10, |
||||||
|
'balanceMaxShift' => 1, |
||||||
|
'balanceCooldown' => 3, |
||||||
|
], |
||||||
|
], |
||||||
|
|
||||||
|
'local' => [ |
||||||
|
'supervisor-1' => [ |
||||||
|
'maxProcesses' => 3, |
||||||
|
], |
||||||
|
], |
||||||
|
], |
||||||
|
]; |
||||||
@ -1,32 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration; |
|
||||||
use Illuminate\Database\Schema\Blueprint; |
|
||||||
use Illuminate\Support\Facades\Schema; |
|
||||||
|
|
||||||
return new class extends Migration |
|
||||||
{ |
|
||||||
/** |
|
||||||
* Run the migrations. |
|
||||||
* |
|
||||||
* @return void |
|
||||||
*/ |
|
||||||
public function up() |
|
||||||
{ |
|
||||||
Schema::create('password_resets', function (Blueprint $table) { |
|
||||||
$table->string('email')->index(); |
|
||||||
$table->string('token'); |
|
||||||
$table->timestamp('created_at')->nullable(); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Reverse the migrations. |
|
||||||
* |
|
||||||
* @return void |
|
||||||
*/ |
|
||||||
public function down() |
|
||||||
{ |
|
||||||
Schema::dropIfExists('password_resets'); |
|
||||||
} |
|
||||||
}; |
|
||||||
@ -1,37 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration; |
|
||||||
use Illuminate\Database\Schema\Blueprint; |
|
||||||
use Illuminate\Support\Facades\Schema; |
|
||||||
|
|
||||||
return new class extends Migration |
|
||||||
{ |
|
||||||
/** |
|
||||||
* Run the migrations. |
|
||||||
* |
|
||||||
* @return void |
|
||||||
*/ |
|
||||||
public function up() |
|
||||||
{ |
|
||||||
Schema::create('personal_access_tokens', function (Blueprint $table) { |
|
||||||
$table->id(); |
|
||||||
$table->morphs('tokenable'); |
|
||||||
$table->string('name'); |
|
||||||
$table->string('token', 64)->unique(); |
|
||||||
$table->text('abilities')->nullable(); |
|
||||||
$table->timestamp('last_used_at')->nullable(); |
|
||||||
$table->timestamp('expires_at')->nullable(); |
|
||||||
$table->timestamps(); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Reverse the migrations. |
|
||||||
* |
|
||||||
* @return void |
|
||||||
*/ |
|
||||||
public function down() |
|
||||||
{ |
|
||||||
Schema::dropIfExists('personal_access_tokens'); |
|
||||||
} |
|
||||||
}; |
|
||||||
@ -0,0 +1,3 @@ |
|||||||
|
create database testing; |
||||||
|
GRANT ALL ON `testing`.* TO 'sail'@'%'; |
||||||
|
FLUSH PRIVILEGES; |
||||||
@ -1,19 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
use Illuminate\Http\Request; |
|
||||||
use Illuminate\Support\Facades\Route; |
|
||||||
|
|
||||||
/* |
|
||||||
|-------------------------------------------------------------------------- |
|
||||||
| API Routes |
|
||||||
|-------------------------------------------------------------------------- |
|
||||||
| |
|
||||||
| Here is where you can register API routes for your application. These |
|
||||||
| routes are loaded by the RouteServiceProvider within a group which |
|
||||||
| is assigned the "api" middleware group. Enjoy building your API! |
|
||||||
| |
|
||||||
*/ |
|
||||||
|
|
||||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) { |
|
||||||
return $request->user(); |
|
||||||
}); |
|
||||||
@ -0,0 +1,10 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route; |
||||||
|
|
||||||
|
Route::prefix('convert')->group(function () { |
||||||
|
Route::post('{format}', [ |
||||||
|
\App\Http\Controllers\V1\ConvertController::class, |
||||||
|
'convert' |
||||||
|
]); |
||||||
|
}); |
||||||
@ -0,0 +1,40 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Tests\Feature\Upload; |
||||||
|
|
||||||
|
use App\Jobs\ChunkFile; |
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase; |
||||||
|
use Illuminate\Foundation\Testing\WithFaker; |
||||||
|
use Illuminate\Http\Testing\File; |
||||||
|
use Illuminate\Support\Facades\Bus; |
||||||
|
use Illuminate\Support\Facades\Storage; |
||||||
|
use Tests\TestCase; |
||||||
|
|
||||||
|
class ConvertJsonTest extends TestCase |
||||||
|
{ |
||||||
|
/** |
||||||
|
* upload json file. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
* @group convert |
||||||
|
*/ |
||||||
|
public function test_example() |
||||||
|
{ |
||||||
|
$content = file_get_contents(base_path('/tests/Storage/ConvertJsonTest.json')); |
||||||
|
$file = File::createWithContent( |
||||||
|
'test.json', |
||||||
|
$content |
||||||
|
); |
||||||
|
|
||||||
|
Bus::fake(); |
||||||
|
Storage::fake(); |
||||||
|
|
||||||
|
$this->post('/api/v1/convert/json', [ |
||||||
|
'file' => $file |
||||||
|
]) |
||||||
|
->assertSuccessful(); |
||||||
|
|
||||||
|
Storage::assertExists($file->name); |
||||||
|
Bus::assertDispatched(ChunkFile::class, 1); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,98 @@ |
|||||||
|
[ |
||||||
|
{ |
||||||
|
"name": "Mrs. Daphney Borer1", |
||||||
|
"address": "57465 Kelton Trace Suite 676 49508-4359 Lake Iliana", |
||||||
|
"checked": false, |
||||||
|
"description": "Quae quia at quae aut quaerat dolore consectetur. Quaerat saepe perferendis incidunt sapiente optio reiciendis. Rerum inventore et adipisci dolores possimus est voluptas qui.<br>Quis harum reiciendis ipsum. Aliquam quam commodi repellat occaecati. Aut et quam vel cumque eaque est.", |
||||||
|
"interest": "leverage cross-media communities", |
||||||
|
"date_of_birth": "1974-06-30T15:41:42+00:00", |
||||||
|
"email": "flatley.laurie@damore.com", |
||||||
|
"account": "2454926431051", |
||||||
|
"credit_card": { |
||||||
|
"type": "Visa", |
||||||
|
"number": "4532623545165", |
||||||
|
"name": "Grace Kilback", |
||||||
|
"expirationDate": "02\/18" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Mrs. Daphney Borer2", |
||||||
|
"address": "57465 Kelton Trace Suite 676 49508-4359 Lake Iliana", |
||||||
|
"checked": false, |
||||||
|
"description": "Quae quia at quae aut quaerat dolore consectetur. Quaerat saepe perferendis incidunt sapiente optio reiciendis. Rerum inventore et adipisci dolores possimus est voluptas qui.<br>Quis harum reiciendis ipsum. Aliquam quam commodi repellat occaecati. Aut et quam vel cumque eaque est.", |
||||||
|
"interest": "leverage cross-media communities", |
||||||
|
"date_of_birth": "1974-06-30T15:41:42+00:00", |
||||||
|
"email": "flatley.laurie@damore.com", |
||||||
|
"account": "2454926431051", |
||||||
|
"credit_card": { |
||||||
|
"type": "Visa", |
||||||
|
"number": "4532623545165", |
||||||
|
"name": "Grace Kilback", |
||||||
|
"expirationDate": "02\/18" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Mrs. Daphney Borer3", |
||||||
|
"address": "57465 Kelton Trace Suite 676 49508-4359 Lake Iliana", |
||||||
|
"checked": false, |
||||||
|
"description": "Quae quia at quae aut quaerat dolore consectetur. Quaerat saepe perferendis incidunt sapiente optio reiciendis. Rerum inventore et adipisci dolores possimus est voluptas qui.<br>Quis harum reiciendis ipsum. Aliquam quam commodi repellat occaecati. Aut et quam vel cumque eaque est.", |
||||||
|
"interest": "leverage cross-media communities", |
||||||
|
"date_of_birth": "1974-06-30T15:41:42+00:00", |
||||||
|
"email": "flatley.laurie@damore.com", |
||||||
|
"account": "2454926431051", |
||||||
|
"credit_card": { |
||||||
|
"type": "Visa", |
||||||
|
"number": "4532623545165", |
||||||
|
"name": "Grace Kilback", |
||||||
|
"expirationDate": "02\/18" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Mrs. Daphney Borer4", |
||||||
|
"address": "57465 Kelton Trace Suite 676 49508-4359 Lake Iliana", |
||||||
|
"checked": false, |
||||||
|
"description": "Quae quia at quae aut quaerat dolore consectetur. Quaerat saepe perferendis incidunt sapiente optio reiciendis. Rerum inventore et adipisci dolores possimus est voluptas qui.<br>Quis harum reiciendis ipsum. Aliquam quam commodi repellat occaecati. Aut et quam vel cumque eaque est.", |
||||||
|
"interest": "leverage cross-media communities", |
||||||
|
"date_of_birth": "1974-06-30T15:41:42+00:00", |
||||||
|
"email": "flatley.laurie@damore.com", |
||||||
|
"account": "2454926431051", |
||||||
|
"credit_card": { |
||||||
|
"type": "Visa", |
||||||
|
"number": "4532623545165", |
||||||
|
"name": "Grace Kilback", |
||||||
|
"expirationDate": "02\/18" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Mrs. Daphney Borer5", |
||||||
|
"address": "57465 Kelton Trace Suite 676 49508-4359 Lake Iliana", |
||||||
|
"checked": false, |
||||||
|
"description": "Quae quia at quae aut quaerat dolore consectetur. Quaerat saepe perferendis incidunt sapiente optio reiciendis. Rerum inventore et adipisci dolores possimus est voluptas qui.<br>Quis harum reiciendis ipsum. Aliquam quam commodi repellat occaecati. Aut et quam vel cumque eaque est.", |
||||||
|
"interest": "leverage cross-media communities", |
||||||
|
"date_of_birth": "1974-06-30T15:41:42+00:00", |
||||||
|
"email": "flatley.laurie@damore.com", |
||||||
|
"account": "2454926431051", |
||||||
|
"credit_card": { |
||||||
|
"type": "Visa", |
||||||
|
"number": "4532623545165", |
||||||
|
"name": "Grace Kilback", |
||||||
|
"expirationDate": "02\/18" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Mrs. Daphney Borer6", |
||||||
|
"address": "57465 Kelton Trace Suite 676 49508-4359 Lake Iliana", |
||||||
|
"checked": false, |
||||||
|
"description": "Quae quia at quae aut quaerat dolore consectetur. Quaerat saepe perferendis incidunt sapiente optio reiciendis. Rerum inventore et adipisci dolores possimus est voluptas qui.<br>Quis harum reiciendis ipsum. Aliquam quam commodi repellat occaecati. Aut et quam vel cumque eaque est.", |
||||||
|
"interest": "leverage cross-media communities", |
||||||
|
"date_of_birth": "1974-06-30T15:41:42+00:00", |
||||||
|
"email": "flatley.laurie@damore.com", |
||||||
|
"account": "2454926431051", |
||||||
|
"credit_card": { |
||||||
|
"type": "Visa", |
||||||
|
"number": "4532623545165", |
||||||
|
"name": "Grace Kilback", |
||||||
|
"expirationDate": "02\/18" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Tests\Unit\Jobs; |
||||||
|
|
||||||
|
use App\Enums\FileFormatEnum; |
||||||
|
use App\Jobs\ChunkFile; |
||||||
|
use App\Jobs\StoreChunk; |
||||||
|
use Illuminate\Support\Facades\Queue; |
||||||
|
use Illuminate\Support\Facades\Storage; |
||||||
|
use Illuminate\Support\Str; |
||||||
|
use Tests\TestCase; |
||||||
|
use Illuminate\Support\Facades\Bus; |
||||||
|
|
||||||
|
class ChunkFileTest extends TestCase |
||||||
|
{ |
||||||
|
/** |
||||||
|
* A basic unit test example. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
* @group convert |
||||||
|
*/ |
||||||
|
public function test_chunk_json_file() |
||||||
|
{ |
||||||
|
Bus::fake(); |
||||||
|
|
||||||
|
$path = base_path('/tests/Storage/ConvertJsonTest.json'); |
||||||
|
|
||||||
|
Storage::shouldReceive('path')->andReturn($path); |
||||||
|
Storage::shouldReceive('delete')->andReturnTrue(); |
||||||
|
|
||||||
|
(new ChunkFile( |
||||||
|
Str::uuid(), |
||||||
|
$path, |
||||||
|
FileFormatEnum::JSON |
||||||
|
))->handle(); |
||||||
|
|
||||||
|
Bus::assertDispatched(StoreChunk::class, 1); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Tests\Unit\Jobs; |
||||||
|
|
||||||
|
use App\Jobs\StoreChunk; |
||||||
|
use App\Models\User; |
||||||
|
use Illuminate\Database\Eloquent\Factories\Sequence; |
||||||
|
use Tests\TestCase; |
||||||
|
|
||||||
|
class StoreChunkTest extends TestCase |
||||||
|
{ |
||||||
|
/** |
||||||
|
* A basic unit test example. |
||||||
|
* |
||||||
|
* @return void |
||||||
|
* @group convert2 |
||||||
|
*/ |
||||||
|
public function test_store_chunk() |
||||||
|
{ |
||||||
|
(new StoreChunk( |
||||||
|
User::factory()->count(99)->state( |
||||||
|
new Sequence( |
||||||
|
[ |
||||||
|
'date_of_birth' => fake()->dateTimeBetween('-70 years', '-66 years'), |
||||||
|
], |
||||||
|
[ |
||||||
|
'date_of_birth' => fake()->dateTimeBetween('-65 years', '-18 years'), |
||||||
|
], |
||||||
|
[ |
||||||
|
'date_of_birth' => fake()->dateTimeBetween('-18 years', 'now'), |
||||||
|
] |
||||||
|
) |
||||||
|
)->make()->toArray() |
||||||
|
))->handle(); |
||||||
|
|
||||||
|
$this->assertDatabaseCount('users', 33); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue