Mon Jul 8
storage/app/public/images/HELL/originalFileName.extension
. The image column saves only the name as it already appears.$this->model()->path
. At a resource level we can get the model columns used because it's defined as $this->model. Because we're on the detail view the path in this case is filled in. We don't need methods that include the models.This is one of the biggest "aha!" moments with Nova where the docs aren't very intuitive nor do they promote this in any meaningful way in the examples I've seen.
Image::make('Header Image', 'image')
->disk('public')
->store(function (Request $request, \App\Models\Bucket $model) {
$path = "images/{$model->path}";
$file = $request->image->storeAs($path, $request->image->getClientOriginalName(), 'public');
return [
'image' => $request->image->getClientOriginalName(),
];
})
->prunable()
->preview(function ($image, $disk) {
return $image ? \Storage::disk($disk)->url("images/{$this->model()->path}/$image") : null;
})
->thumbnail(function ($image, $disk) {
return $image ? \Storage::disk($disk)->url("images/{$this->model()->path}/$image") : null;
}),
Tue Jul 9
getPathAttribute()
essentially creates our path value in the same way from our slug and it's only used during the create model upload.This is sleight of hand at its finest, the real path column is what we're looking for but we're hacking in functionality to work at the create form level, bypassing the need to restrict this to only during edits.
public function getPathAttribute()
{
$path = (array_has($this->attributes, 'path') && $this->attributes['path']) ? $this->attributes['path'] : null;
// We only care to calculate the path in the same manner as our creating method when the model is first used
if ($path === null) {
$slug = (array_has($this->attributes, 'slug') && $this->attributes['slug']) ? static::stripSpecialCharacters($this->attributes['slug']) : null;
return $slug;
}
return $path;
}
protected static function boot()
{
parent::boot();
static::created(function(Bucket $bucket) {
$bucket->path = static::stripSpecialCharacters($bucket->slug);
$bucket->save();
});
}
Wed Jul 10
Filter the specific keys to look for:
> keys horizon:queue*
1) "horizon:queues:orders:transfer:reserved"
2) "horizon:queue:orders:transform"
3) "horizon:queue:orders:transfer"
4) "horizon:queues:orders:transfer"
Get the type of our keys:
> type "horizon:queues:orders:transfer:reserved"
zset
> type "horizon:queue:orders:transform"
hash
> type "horizon:queue:orders:transfer"
hash
> type "horizon:queues:orders:transfer"
list
> type "horizon:job:App\\Jobs\\PendingOrderTransformJob"
hash
> type "horizon:job:App\\Jobs\\PendingOrderTransferJob"
hash
Look at the values for the specific keys:
> zrange "horizon:queues:orders:transfer:reserved" 0 2 WITHSCORES
1) "{\"type\":\"job\",\"timeout\":null,\"tags\":[\"App\\\\Model\\\\PendingOrderStatus:1258\"],\"id\":\"2520\",\"data\":{\"command\":\"O:32:\\\"App\\\\Jobs\\\\PendingOrderTransferJob\\\":8:{s:9:\\\"\\u0000*\\u0000status\\\";O:45:\\\"Illuminate\\\\Contracts\\\\Database\\\\ModelIdentifier\\\":3:{s:5:\\\"class\\\";s:28:\\\"App\\\\Model\\\\PendingOrderStatus\\\";s:2:\\\"id\\\";i:1258;s:10:\\\"connection\\\";s:5:\\\"mysql\\\";}s:6:\\\"\\u0000*\\u0000job\\\";N;s:10:\\\"connection\\\";s:13:\\\"redis:horizon\\\";s:5:\\\"queue\\\";s:15:\\\"orders:transfer\\\";s:15:\\\"chainConnection\\\";N;s:10:\\\"chainQueue\\\";N;s:5:\\\"delay\\\";N;s:7:\\\"chained\\\";a:0:{}}\",\"commandName\":\"App\\\\Jobs\\\\PendingOrderTransferJob\"},\"displayName\":\"App\\\\Jobs\\\\PendingOrderTransferJob\",\"timeoutAt\":1562789478,\"pushedAt\":\"1562787678.5943\",\"maxTries\":null,\"job\":\"Illuminate\\\\Queue\\\\CallQueuedHandler@call\",\"attempts\":3}"
2) "1562788306"
> hgetall "horizon:queue:orders:transfer"
1) "throughput"
2) "52"
3) "runtime"
4) "5623.0248076923099"
> lrange "horizon:queues:orders:transfer" 0 99
...
47) "{\"type\":\"job\",\"timeout\":null,\"tags\":[\"App\\\\Model\\\\PendingOrderStatus:1280\"],\"id\":\"2564\",\"data\":{\"command\":\"O:32:\\\"App\\\\Jobs\\\\PendingOrderTransferJob\\\":8:{s:9:\\\"\\u0000*\\u0000status\\\";O:45:\\\"Illuminate\\\\Contracts\\\\Database\\\\ModelIdentifier\\\":3:{s:5:\\\"class\\\";s:28:\\\"App\\\\Model\\\\PendingOrderStatus\\\";s:2:\\\"id\\\";i:1280;s:10:\\\"connection\\\";s:5:\\\"mysql\\\";}s:6:\\\"\\u0000*\\u0000job\\\";N;s:10:\\\"connection\\\";s:13:\\\"redis:horizon\\\";s:5:\\\"queue\\\";s:15:\\\"orders:transfer\\\";s:15:\\\"chainConnection\\\";N;s:10:\\\"chainQueue\\\";N;s:5:\\\"delay\\\";N;s:7:\\\"chained\\\";a:0:{}}\",\"commandName\":\"App\\\\Jobs\\\\PendingOrderTransferJob\"},\"displayName\":\"App\\\\Jobs\\\\PendingOrderTransferJob\",\"timeoutAt\":1562789480,\"pushedAt\":\"1562787680.4057\",\"maxTries\":null,\"job\":\"Illuminate\\\\Queue\\\\CallQueuedHandler@call\",\"attempts\":3}"
> hgetall "horizon:job:App\\Jobs\\PendingOrderTransferJob"
1) "throughput"
2) "7"
3) "runtime"
4) "7738.0300000000007"
Dump our entire key list (the -n
option specifies the database):
> redis-cli -n 3 keys "*" > horizon.keys
horizon:snapshot:job:App\\Jobs\\PendingOrderTransformJob
horizon:supervisor:orange-business-rules-swap-f6S1:supervisor-order-transform
horizon:job:App\\Jobs\\PendingOrderTransformJob
horizon:failed_jobs
horizon:snapshot:job:App\\Jobs\\PendingOrderTransferJob
horizon:masters
horizon:job_id
horizon:queues:orders:transfer:reserved
horizon:snapshot:queue:orders:transform
horizon:supervisor:orange-business-rules-swap-f6S1:supervisor-default
horizon:supervisor:orange-business-rules-swap-f6S1:supervisor-order-transfer
horizon:supervisors
horizon:recent_failed_jobs
horizon:master:orange-business-rules-swap-f6S1
horizon:job:App\\Jobs\\PendingOrderTransferJob
horizon:measured_jobs
horizon:queue:orders:transform
horizon:measured_queues
horizon:recent_jobs
horizon:queue:orders:transfer
horizon:last_snapshot_at
horizon:monitor:time-to-clear
horizon:snapshot:queue:orders:transfer
horizon:metrics:snapshot
horizon:queues:orders:transfer
horizon:id
or horizon:failed*
.Thu Jul 11
Do not use Redis::throtle()
with the retryUntil()
method.
Redis::throttle($key)->allow(1)->every(60)->then(function () {
$this->execute();
}, function () {
// Could not obtain lock...
return $this->release(10);
});
/**
* Determine the time at which the job should timeout.
*
* @return \DateTime
*/
public function retryUntil()
{
return now()->addMinutes(60);
}
Fri Jul 12
Setting a redis override for our custom systemd configuration
sudo systemctl edit redis-server
The command opens nano to an override file in /etc/systemd/system where we paste the following:
[Service]
ReadWriteDirectories=-/mnt/orange-business-rules/var/lib/redis
Thu Jul 11
Maps
Map.fetch(@person, :age)
returns {:ok, value}MapSets
MapSet.size(new_set)
returns an integer for the size (think array length in JavaScript)MapSet.member?(@set, 3)
returns a booleanMapSet.new(@set, fn x -> 3 * x end)
creates a new set using the function results of 3 * (each value in the set).MapSet.to_list(@set)
looks for brackets not braces. I confused a list with a tuple.