Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jobs Refactor #391

Merged
merged 13 commits into from Mar 5, 2024
Merged

Jobs Refactor #391

merged 13 commits into from Mar 5, 2024

Conversation

adam-fowler
Copy link
Member

@adam-fowler adam-fowler commented Feb 26, 2024

This refactor is required as it has been pointed out accessing services from a job is quite hard with the current structure. The changes include a breaking up of what defines a job and an actual job instance with parameters. I've also added a JobIdentifier which also includes a reference to the parameter type used by the job to ensure we don't pass bad parameters to a job.

// define email job parameters
struct EmailJobParameters: Codable {
    let recipient: String
    let subject: String
    let message: String
}

// add identifier for email job and associate with EmailJobParameters type
extension HBJobIdentifier<EmailJobParameters> {
    static var email: Self { .init(name: "email-job") }
}

// Create job queue
let jobQueue = HBJobQueue(.redis(...), maxWorkers: 4, logger: logger)

let ses = SES()

// register email job, with job functionality
jobQueue.registerJob(.email) { parameters, context in
    try await ses.sendEmail(to: parameters.recipient, subject: parameters.subject, body: parameters.message)
}

//  Push email job to queue. Because we have the association between
// the identifier and the required parameters we can ensure the correct parameter type
// is passed in
jobQueue.push(
    id: .email, 
    parameters: .init(recipient: "adam@gmail.com", subject:"Test", message: "Testing, testing, 123")
)

@adam-fowler adam-fowler changed the base branch from main to 2.x.x February 26, 2024 14:13
@adam-fowler adam-fowler marked this pull request as draft February 26, 2024 14:13
Copy link

codecov bot commented Feb 26, 2024

Codecov Report

Attention: Patch coverage is 88.88889% with 17 lines in your changes are missing coverage. Please review.

Project coverage is 84.46%. Comparing base (8cb3e42) to head (f130b57).
Report is 2 commits behind head on 2.x.x.

Files Patch % Lines
Sources/HummingbirdJobs/JobRegistry.swift 80.00% 11 Missing ⚠️
Sources/HummingbirdJobs/JobQueueHandler.swift 88.46% 3 Missing ⚠️
Sources/HummingbirdJobs/JobIdentifier.swift 75.00% 1 Missing ⚠️
Sources/HummingbirdJobs/JobQueueError.swift 0.00% 1 Missing ⚠️
...obs/Utils/DecodableWithUserInfoConfiguration.swift 90.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            2.x.x     #391      +/-   ##
==========================================
+ Coverage   84.39%   84.46%   +0.06%     
==========================================
  Files          94       99       +5     
  Lines        5282     5342      +60     
==========================================
+ Hits         4458     4512      +54     
- Misses        824      830       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@adam-fowler
Copy link
Member Author

adam-fowler commented Feb 26, 2024

For reference this is what the Jobs framework did previously with comment indicating the issue I'm trying to fix

let see = SES()

struct EmailJob: HBJob {
    let recipient: String
    let subject: String
    let message: String

    func execute(logger: Logger) async throws {
        // How do I get access to ses to send the email here?
        // I can't include it in the init as the job is recreated by queue
        // at a later date, I can't use variable capture as I would in a closure
    }
}

EmailJob.register()

// Create job queue
let jobQueue = HBRedisJobQueue()

jobQueue.push(EmailJob(recipient: "adam@gmail.com", subject:"Test", message: "Testing, testing, 123"))

@adam-fowler adam-fowler marked this pull request as ready for review February 27, 2024 13:27
func onInit() async throws
/// Push Job onto queue
/// - Returns: Identifier of queued job
func push(data: Data) async throws -> JobID
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we're using Data here, instead of ByteBuffer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the fact we are moving back and forward between the two types. Should probably change to ByteBuffer.

func shutdownGracefully() async
@discardableResult public func push<Parameters: Codable & Sendable>(id: HBJobIdentifier<Parameters>, parameters: Parameters) async throws -> Queue.JobID {
let jobRequest = HBJobRequest(id: id, parameters: parameters)
let data = try JSONEncoder().encode(jobRequest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to allow drivers to encode these parameters (or the request as a whole)? In MongoDB, it would be really unfortunate to encode this to JSON, then add the JSON into MongoDB. Since MongoDB already has (recursive) object support. So it would be able to store this as-is in BSON. Encoding to JSON would prevent indexes from being applies to id, and inspecting the data in MongoDB would require quite a lot of work from the developer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that the driver only stores data blobs. Do you see an advantage to storing the full object structure? I guess debugging job issues might be easier.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debugging mainly, yes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had moved away from the allowing drivers to do the encoding because I was repeating the same code across all of the drivers. It also meant the driver needed to know about the job registry so they could be sure to decode the correct job type. Data blobs meant the driver had a clean split from the job decoding. I'll have another look though.

@adam-fowler adam-fowler merged commit b5fd7d4 into 2.x.x Mar 5, 2024
6 checks passed
@adam-fowler adam-fowler deleted the 2.x.x-jobs-refactor branch March 5, 2024 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants