Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Hummingbird.docc/HummingbirdValkey/HummingbirdValkey.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ try await app.runService()

## See Also

- ``JobsRedis``
- ``JobsValkey``
2 changes: 1 addition & 1 deletion Hummingbird.docc/Jobs/JobQueueDriver.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ Defines the requirements for job queue implementation.
### Implementations

- ``memory``
- ``redis(_:configuration:logger:)``
- ``valkey(_:configuration:logger:)``
- ``postgres(client:migrations:configuration:logger:)``
2 changes: 1 addition & 1 deletion Hummingbird.docc/Jobs/Jobs.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,5 @@ A Job consists of a payload and an execute method to run the job. `Jobs` provide

## See Also

- ``JobsRedis``
- ``JobsValkey``
- ``JobsPostgres``
4 changes: 2 additions & 2 deletions Hummingbird.docc/Jobs/JobsGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Offload work your server would be doing to another server.

## Overview

A Job consists of a payload and an execute method to run the job. Swift Jobs provides a framework for pushing jobs onto a queue and processing them at a later point. If the driver backing up the job queue uses persistent storage then a separate server can be used to process the jobs. The module comes with a driver that stores jobs in local memory and uses your current server to process the jobs, but there are also implementations in ``JobsRedis`` and ``JobsPostgres`` that implement the job queue using a Redis database or Postgres database.
A Job consists of a payload and an execute method to run the job. Swift Jobs provides a framework for pushing jobs onto a queue and processing them at a later point. If the driver backing up the job queue uses persistent storage then a separate server can be used to process the jobs. The module comes with a driver that stores jobs in local memory and uses your current server to process the jobs, but there are also implementations in ``JobsValkey`` and ``JobsPostgres`` that implement the job queue using a Valkey/Redis database or Postgres database.

### Setting up a Job queue

Expand Down Expand Up @@ -84,7 +84,7 @@ Or it can be added to the array of services that `Application` manages
let app = Application(...)
app.addServices(jobProcessor)
```
If you want to process jobs on a separate server you will need to use a job queue driver that saves to some external storage eg ``JobsRedis/RedisJobQueue`` or ``JobsPostgres/PostgresJobQueue``.
If you want to process jobs on a separate server you will need to use a job queue driver that saves to some external storage eg ``JobsValkey/ValkeyJobQueue`` or ``JobsPostgres/PostgresJobQueue``.

## Job Scheduler

Expand Down
2 changes: 1 addition & 1 deletion Hummingbird.docc/JobsPostgres/JobsPostgres.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,6 @@ You can find out more about the Job scheduler in the Jobs guide <doc:JobsGuide#J
## See Also

- ``Jobs``
- ``JobsRedis``
- ``JobsValkey``
- ``Hummingbird``
- ``HummingbirdPostgres``
134 changes: 0 additions & 134 deletions Hummingbird.docc/JobsRedis/JobsRedis.md

This file was deleted.

139 changes: 139 additions & 0 deletions Hummingbird.docc/JobsValkey/JobsValkey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# ``JobsValkey``

@Metadata {
@PageImage(purpose: icon, source: "logo")
}

Valkey/Redis implementation for Hummingbird jobs framework

## Overview

Hummingbird Jobs Queue driver using [valkey-swift](https://github.com/valkey-io/valkey-swift).

## Setup

The Postgres job queue driver uses `ValkeyClient` from `valkey-swift`.

The Valkey job queue configuration includes three values.
- `pollTime`: This is the amount of time between the last time the queue was empty and the next time the driver starts looking for pending jobs.
- `queueName`: Name of queue used to differentiate itself from other queues.
- `retentionPolicy`: Policy on what jobs are retained.

```swift
import JobsValkey
import ServiceLifecycle
import Valkey

let valkeyClient = ValkeyClient(...)
let jobQueue = JobQueue(
.valkey(
valkeyClient,
configuration: .init(
queueName: "MyJobQueue",
pollTime: .milliseconds(50)
)
),
logger: logger
)
```

## Additional Features

There are features specific to the Valkey/Redis Job Queue implementation.

### Push Options

When pushing a job to the queue there are a number of options you can provide.

#### Delaying jobs

As with all queue drivers you can add a delay before a job is processed. The job will sit in the pending queue and will not be available for processing until time has passed its delay until time.

```swift
// Add TestJob to the queue, but don't process it for 2 minutes
try await jobQueue.push(TestJob(), options: .init(delayUntil: .now + 120))
```

### Cancellation

The ``JobsValkey/ValkeyJobQueue`` conforms to protocol ``Jobs/CancellableJobQueue``. This requires support for cancelling jobs that are in the pending queue. It adds one new function ``JobsValkey/ValkeyJobQueue/cancel(jobID:)``. If you supply this function with the `JobID` returned by ``JobsValkey/ValkeyJobQueue/push(_:options:)`` it will remove it from the pending queue.

```swift
// Add TestJob to the queue and immediately cancel it
let jobID = try await jobQueue.push(TestJob(), options: .init(delayUntil: .now + 120))
try await jobQueue.cancel(jobID: jobID)
```

### Pause and Resume

The ``JobsValkey/ValkeyJobQueue`` conforms to protocol ``Jobs/ResumableJobQueue``. This requires support for pausing and resuming jobs that are in the pending queue. It adds two new functions ``JobsValkey/ValkeyJobQueue/pause(jobID:)`` and ``JobsValkey/ValkeyJobQueue/resume(jobID:)``. If you supply these function with the `JobID` returned by ``JobsValkey/ValkeyJobQueue/push(_:options:)`` you can remove from the pending queue and add them back in at a later date.

```swift
// Add TestJob to the queue and immediately remove it and then add it back to the queue
let jobID = try await jobQueue.push(TestJob(), options: .init(delayUntil: .now + 120))
try await jobQueue.pause(jobID: jobID)
try await jobQueue.resume(jobID: jobID)
```

### Job retention

The queue has options to retain jobs once it has finished with them depending on status. By default the queue will retain failed jobs and drop cancelled or completed jobs, but these decisions are configurable.

```swift
let jobQueue = JobQueue(
.valkey(
valkeyClient,
configuration: .init(
queueKey: "MyJobQueue",
retentionPolicy: .init(
completedJobs: .retain,
failedJobs: .retain,
cancelledJobs: .doNotRetain
)
)
),
logger: logger
)
```

### Job queue cleanup

If you do opt to retain jobs after processing you will probably eventually want to clean them up. The Valkey/Redis queue provides a method `cleanup` which allows you to remove or attempt to re-run jobs based on what state they are in. You should be careful not to do anything to pending or processing jobs while the job queue is being processed as it might confuse the job processor.

```swift
jobQueue.queue.cleanup(
pendingJobs: .doNothing,
processingJobs: .doNothing,
completedJobs: .remove(maxAge: .seconds(7*24*60*60)),
failedJobs: .rerun,
cancelledJobs: .remove,
pausedJobs: .doNothing
)
```

#### Scheduling cleanup

Given this is a job you will probably want to do regularly the queue also provides a job you can use in conjunction with the `JobScheduler` that will do the cleanup for you.

```swift
var jobSchedule = JobSchedule()
jobSchedule.addJob(
jobQueue.queue.cleanupJob,
parameters: .init(completedJobs: .remove, failedJobs: .rerun, cancelledJobs: .remove, pausedJobs: .doNothing),
schedule: .weekly(day: .sunday)
)
```

You can find out more about the Job scheduler in the Jobs guide <doc:JobsGuide#Job-Scheduler>

## Topics

### Job Queue

- ``ValkeyJobQueue``

## See Also

- ``Jobs``
- ``JobsPostgres``
- ``Hummingbird``
10 changes: 5 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ let package = Package(
.package(url: "https://github.com/hummingbird-project/hummingbird-auth.git", from: "2.0.0"),
.package(url: "https://github.com/hummingbird-project/hummingbird-compression.git", from: "2.0.0"),
.package(url: "https://github.com/hummingbird-project/hummingbird-fluent.git", from: "2.0.0"),
.package(url: "https://github.com/hummingbird-project/swift-jobs.git", from: "1.0.0-rc"),
.package(url: "https://github.com/hummingbird-project/swift-jobs-postgres.git", from: "1.0.0-rc"),
.package(url: "https://github.com/hummingbird-project/swift-jobs-redis.git", from: "1.0.0-rc"),
.package(url: "https://github.com/hummingbird-project/swift-jobs.git", from: "1.0.0"),
.package(url: "https://github.com/hummingbird-project/swift-jobs-postgres.git", from: "1.0.0"),
.package(url: "https://github.com/hummingbird-project/swift-jobs-valkey.git", from: "1.0.0-rc.2"),
.package(url: "https://github.com/hummingbird-project/hummingbird-lambda.git", from: "2.0.0-rc.5"),
.package(url: "https://github.com/hummingbird-project/swift-mustache.git", from: "2.0.0"),
.package(url: "https://github.com/hummingbird-project/hummingbird-postgres.git", from: "1.0.0-rc"),
.package(url: "https://github.com/hummingbird-project/postgres-migrations.git", from: "1.0.0-rc"),
.package(url: "https://github.com/hummingbird-project/postgres-migrations.git", from: "1.0.0"),
.package(url: "https://github.com/hummingbird-project/hummingbird-valkey.git", from: "0.1.1"),
.package(url: "https://github.com/hummingbird-project/hummingbird-websocket.git", from: "2.2.0"),
.package(url: "https://github.com/hummingbird-project/swift-websocket.git", from: "1.2.0"),
Expand All @@ -47,7 +47,7 @@ let package = Package(
.product(name: "HummingbirdCompression", package: "hummingbird-compression"),
.product(name: "HummingbirdFluent", package: "hummingbird-fluent"),
.product(name: "Jobs", package: "swift-jobs"),
.product(name: "JobsRedis", package: "swift-jobs-redis"),
.product(name: "JobsValkey", package: "swift-jobs-valkey"),
.product(name: "JobsPostgres", package: "swift-jobs-postgres"),
.product(name: "HummingbirdLambda", package: "hummingbird-lambda"),
.product(name: "HummingbirdLambdaTesting", package: "hummingbird-lambda"),
Expand Down