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

Remove provider references from function arguments #1397

Open
insipx opened this issue Dec 10, 2024 · 0 comments
Open

Remove provider references from function arguments #1397

insipx opened this issue Dec 10, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@insipx
Copy link
Contributor

insipx commented Dec 10, 2024

It's not sustainable to refactor provider into functions every couple months, and function duplication into _with_provider variants adds unnecessary noise. We should figure out a longer-term solution to share provider references without the churn.

One possible solution:

  • Create a wrapper unit struct that implements XmtpOpenMlsProvider, but holds a Cow<_>. ProviderRef<'_>
  • ProviderRef will hold an Option<Cow<Provider<'_>>
  • MlsGroup becomes MlsGroup<'a, Client>
  • MlsGroup can be aliased to MlsGroup<'static, Client> for the trivial case where it does not yet hold a provider, or the provider is owned. This should make it possible for all external functions to retain their same function signatures, without proliferating a lifetime everywhere in the code
  • all MlsGroup methods will access a provider through mls_provider() method. Internally, ProviderRef will check for the existence of a provider, and if it exists use the reference. Otherwise, it will pull a new provider

Pros:

  • simplifies provider management, no more &Provider everywhere, or _with_provider
  • to use provider can just call mls_provider()

Cons:

  • could make it trickier to pass a provider down through function codepaths since its hidden behind a unit struct, rather than easily seen from a function signature. This may lead to more opaque error messages about lifetimes

Solution that builds upon this:

we can encapsulate completely the provider management within ProviderRef and pull a new provider if needed within OpenMlsProvider implementation itself. Everywhere we currently accept a provider, we could accept impl OpenMlsProvider or its generic fn<P: OpenMlsProvider>(provider: P) variant. We additionally impement a ProviderExt trait that makes it possible to access Sqlite Connection from this, by appending an additional trait implementation:

trait ProviderExt {
    fn conn_ref(&self) -> &DbConnection;
}

P: OpenMlsProvider + ProviderExt.

This may over-complicate in places for most things esp. with error type management in function callbacks, that would now have to specify something to the effect of

E: From<<P as OpenMlsProvider> as StorageProvider::Error>

which can become more complicated with further nested generics

Rough sketch of Provider Extension Trait

/// This trait would be useful elsewhere too,
/// but it would be a large refactor. For now, it is used in `ProcessMessageFuture`
/// to accept either a Reference or Owned type.
/// `as_ref` is a hack to convert back to a concrete type.
/// In the future, we can replace function arguments with generics for MlsProviderExt

pub trait MlsProviderExt: OpenMlsProvider {
    type DbConnection;
    fn conn_ref(&self) -> &Self::DbConnection;
}

impl<C> MlsProviderExt for XmtpOpenMlsProviderPrivate<C> {
    type DbConnection = DbConnectionPrivate<C>;
    fn conn_ref(&self) -> &Self::DbConnection {
        XmtpOpenMlsProviderPrivate::<C>::conn_ref(self)
    }
}

impl<T> MlsProviderExt for &T where T: MlsProviderExt {
    type DbConnection = <T as MlsProviderExt>::DbConnection;

    fn conn_ref(&self) ->  &Self::DbConnection {
        T::conn_ref(&*self)
    }
}

impl<T> MlsProviderExt for Arc<T> where T: MlsProviderExt {
    type DbConnection = <T as MlsProviderExt>::DbConnection;

    fn conn_ref(&self) -> &Self::DbConnection {
        T::conn_ref(&*self)
    }
}

transaction, async_transaction and retryable_async_transaction could all be implemented on this trait as well.

@insipx insipx added this to libxmtp Dec 10, 2024
@insipx insipx added the enhancement New feature or request label Dec 10, 2024
@insipx insipx moved this to Backlog in libxmtp Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Backlog
Development

No branches or pull requests

1 participant