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

Implement Closeable in FunctionInstanceInjector interface and call close on JVM shutdown #812

Open
ScottHamper opened this issue Feb 18, 2025 · 4 comments
Assignees

Comments

@ScottHamper
Copy link

Azure Functions Java supports dependency injection by implementing com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector and registering the implementation via SPI. However, when the DI container creates resources that need to be closed (via the Closeable interface), those resources will never have their close method called, as Azure Functions and the FunctionInstanceInjector interface provide no way of doing so. Similarly, there does not appear to be any way of closing resources on a graceful shutdown of the Azure Functions runtime/host (See #113, #729).

Official documentation states:

To avoid holding more connections than necessary, reuse client instances rather than creating new ones with each function invocation. We recommend reusing client connections for any language that you might write your function in.

And:

Do not create a new client with every function invocation.

Great - I would like to have my DI container hold a singleton for various clients (e.g., a Ktor HttpClient, or a database client that uses a HikariCP connection pool) and then have function invocations retrieve those clients from the container. Unfortunately, it does not currently seem possible to ensure these resources close properly.

Proposed Solution

Update FunctionInstanceInjector to implement Closeable, and update the Azure Functions runtime to call the close method when the runtime/host shuts down. The AF runtime is currently responsible for creating an instance of FunctionInstanceInjector, so it feels appropriate that it should be responsible for disposing of it.

Here's an example of what I'd like to be able to do (in Kotlin, using the Koin DI library):

abstract class KoinFunctionInstanceInjector(
    appDeclaration: KoinApplication.() -> Unit,
) : FunctionInstanceInjector {
    private val application = koinApplication(appDeclaration)

    override fun <T : Any> getInstance(clazz: Class<T>): T = application.koin.get(clazz.kotlin)

    // Currently a compilation error, because `FunctionInstanceInjector` does not implement `Closeable`
    override fun close() = application.close()
}

Then define a concrete class like:

class MyFunctionInstanceInjector :
    KoinFunctionInstanceInjector({
        modules(
            module {
                single { OkHttp.create() } onClose { it?.close() } bind HttpClientEngine::class
                single { HikariDataSource(/*...*/) } onClose { it?.close() } bind DataSource::class
                // ...
            },
        )
    })

And registering MyFunctionInstanceInjector via SPI. Calling application.close in KoinFunctionInstanceInjector ends up calling the onClose lambda for any/all instance definitions in the Koin module, allowing the HttpClientEngine and HikariDataSource instances to be closed properly.

The only thing missing is ensuring that the MyFunctionInstanceInjector instance that AF creates via SPI will have its close method called.

@ahmedmuhsin
Copy link
Contributor

Hey @ScottHamper ,

Thank you for your feedback. I want to make sure we're on the same page. Are you suggesting that the FunctionInstanceInjector SPI be updated to something like this?

public interface FunctionInstanceInjector extends AutoCloseable {
    
    <T> T getInstance(Class<T> clazz) throws Exception;

    // Default close implementation: no action needed by default
    @Override
    default void close() throws Exception {
        // Default empty implementation to preserve backward compatibility
    }
}

@ScottHamper
Copy link
Author

Yes, @ahmedmuhsin - that looks great!

@ahmedmuhsin
Copy link
Contributor

I've created a draft PR for the SPI update: Azure/azure-functions-java-additions#37

The Java-Worker changes will be linked to this issue once they are done.

@ScottHamper
Copy link
Author

Thank you, @ahmedmuhsin!

@ahmedmuhsin ahmedmuhsin self-assigned this Mar 26, 2025
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

No branches or pull requests

2 participants