You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-29 22:01:14 +03:00
Schedule jobs through the repository
This commit is contained in:
146
crates/storage/src/job.rs
Normal file
146
crates/storage/src/job.rs
Normal file
@ -0,0 +1,146 @@
|
||||
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Repository to schedule persistent jobs.
|
||||
|
||||
pub use apalis_core::job::{Job, JobId};
|
||||
use async_trait::async_trait;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::repository_impl;
|
||||
|
||||
/// A job submission to be scheduled through the repository.
|
||||
pub struct JobSubmission {
|
||||
name: &'static str,
|
||||
payload: Value,
|
||||
}
|
||||
|
||||
impl JobSubmission {
|
||||
/// Create a new job submission out of a [`Job`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the job cannot be serialized.
|
||||
#[must_use]
|
||||
pub fn new<J: Job + Serialize>(job: J) -> Self {
|
||||
Self {
|
||||
name: J::NAME,
|
||||
payload: serde_json::to_value(job).expect("failed to serialize job"),
|
||||
}
|
||||
}
|
||||
|
||||
/// The name of the job.
|
||||
#[must_use]
|
||||
pub fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
|
||||
/// The payload of the job.
|
||||
#[must_use]
|
||||
pub fn payload(&self) -> &Value {
|
||||
&self.payload
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`JobRepository`] is used to schedule jobs to be executed by a worker.
|
||||
#[async_trait]
|
||||
pub trait JobRepository: Send + Sync {
|
||||
/// The error type returned by the repository.
|
||||
type Error;
|
||||
|
||||
/// Schedule a job submission to be executed at a later time.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `submission` - The job to schedule.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`Self::Error`] if the underlying repository fails
|
||||
async fn schedule_submission(
|
||||
&mut self,
|
||||
submission: JobSubmission,
|
||||
) -> Result<JobId, Self::Error>;
|
||||
}
|
||||
|
||||
repository_impl!(JobRepository:
|
||||
async fn schedule_submission(&mut self, submission: JobSubmission) -> Result<JobId, Self::Error>;
|
||||
);
|
||||
|
||||
/// An extension trait for [`JobRepository`] to schedule jobs directly.
|
||||
#[async_trait]
|
||||
pub trait JobRepositoryExt {
|
||||
/// The error type returned by the repository.
|
||||
type Error;
|
||||
|
||||
/// Schedule a job to be executed at a later time.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `job` - The job to schedule.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`Self::Error`] if the underlying repository fails
|
||||
async fn schedule_job<J: Job + Serialize>(&mut self, job: J) -> Result<JobId, Self::Error>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T> JobRepositoryExt for T
|
||||
where
|
||||
T: JobRepository + ?Sized,
|
||||
{
|
||||
type Error = T::Error;
|
||||
|
||||
async fn schedule_job<J: Job + Serialize>(&mut self, job: J) -> Result<JobId, Self::Error> {
|
||||
self.schedule_submission(JobSubmission::new(job)).await
|
||||
}
|
||||
}
|
||||
|
||||
mod jobs {
|
||||
// XXX: Move this somewhere else?
|
||||
use apalis_core::job::Job;
|
||||
use mas_data_model::UserEmail;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ulid::Ulid;
|
||||
|
||||
/// A job to verify an email address.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct VerifyEmailJob {
|
||||
user_email_id: Ulid,
|
||||
}
|
||||
|
||||
impl VerifyEmailJob {
|
||||
/// Create a new job to verify an email address.
|
||||
#[must_use]
|
||||
pub fn new(user_email: &UserEmail) -> Self {
|
||||
Self {
|
||||
user_email_id: user_email.id,
|
||||
}
|
||||
}
|
||||
|
||||
/// The ID of the email address to verify.
|
||||
#[must_use]
|
||||
pub fn user_email_id(&self) -> Ulid {
|
||||
self.user_email_id
|
||||
}
|
||||
}
|
||||
|
||||
impl Job for VerifyEmailJob {
|
||||
const NAME: &'static str = "verify-email";
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::jobs::VerifyEmailJob;
|
@ -150,6 +150,7 @@ pub(crate) mod repository;
|
||||
mod utils;
|
||||
|
||||
pub mod compat;
|
||||
pub mod job;
|
||||
pub mod oauth2;
|
||||
pub mod upstream_oauth2;
|
||||
pub mod user;
|
||||
|
@ -20,6 +20,7 @@ use crate::{
|
||||
CompatAccessTokenRepository, CompatRefreshTokenRepository, CompatSessionRepository,
|
||||
CompatSsoLoginRepository,
|
||||
},
|
||||
job::JobRepository,
|
||||
oauth2::{
|
||||
OAuth2AccessTokenRepository, OAuth2AuthorizationGrantRepository, OAuth2ClientRepository,
|
||||
OAuth2RefreshTokenRepository, OAuth2SessionRepository,
|
||||
@ -192,6 +193,9 @@ pub trait RepositoryAccess: Send {
|
||||
fn compat_refresh_token<'c>(
|
||||
&'c mut self,
|
||||
) -> Box<dyn CompatRefreshTokenRepository<Error = Self::Error> + 'c>;
|
||||
|
||||
/// Get a [`JobRepository`]
|
||||
fn job<'c>(&'c mut self) -> Box<dyn JobRepository<Error = Self::Error> + 'c>;
|
||||
}
|
||||
|
||||
/// Implementations of the [`RepositoryAccess`], [`RepositoryTransaction`] and
|
||||
@ -205,6 +209,7 @@ mod impls {
|
||||
CompatAccessTokenRepository, CompatRefreshTokenRepository, CompatSessionRepository,
|
||||
CompatSsoLoginRepository,
|
||||
},
|
||||
job::JobRepository,
|
||||
oauth2::{
|
||||
OAuth2AccessTokenRepository, OAuth2AuthorizationGrantRepository,
|
||||
OAuth2ClientRepository, OAuth2RefreshTokenRepository, OAuth2SessionRepository,
|
||||
@ -373,6 +378,10 @@ mod impls {
|
||||
&mut self.mapper,
|
||||
))
|
||||
}
|
||||
|
||||
fn job<'c>(&'c mut self) -> Box<dyn JobRepository<Error = Self::Error> + 'c> {
|
||||
Box::new(MapErr::new(self.inner.job(), &mut self.mapper))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: RepositoryAccess + ?Sized> RepositoryAccess for Box<R> {
|
||||
@ -469,5 +478,9 @@ mod impls {
|
||||
) -> Box<dyn CompatRefreshTokenRepository<Error = Self::Error> + 'c> {
|
||||
(**self).compat_refresh_token()
|
||||
}
|
||||
|
||||
fn job<'c>(&'c mut self) -> Box<dyn JobRepository<Error = Self::Error> + 'c> {
|
||||
(**self).job()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user