Closed moltar closed 1 year ago
@moltar how do you think the api should look like?
You can already do subscribe to upserts like:
let node = makeRoot()
.add({
userManual: "Please preheat before use",
oven: () => new Oven(),
})
node.on("containerUpdated", ({ key, newContainer }) => {})
node.on("containerUpserted", ({ key, newContainer }) => {
if(key === "userManual"){
console.log('we've updated our manual')
}
})
node.upsert((containers, node) => ({
userManual: "Works better when hot",
}))
We can also dispose by
node.upsert((containers, node) => ({
userManual: null,
}))
I think I should document this better... Or add some helper functions to make it simpler?
We can also dispose by
But this solution won't await for resources to be freed up (e.g. database disconnected, file handle closed)
Also it feels very verbose.
A few DI frameworks have the concept of disposing or deconstructing, if you will.
I think the interface can be something like this:
class DatabaseConnection {
disconnect(): Promise<void> {
// ... disconnect
}
}
let node = makeRoot()
.add({
db: () => new DatabaseConnection(),
})
.dispose({
db: (containers) => containers.db.disconnect()
})
// disposes of for all resources that have it defined
await node.dispose()
// under the hood (internals)
class Node {
async dispose(): Promise<void> {
await Promise.all( this.disposableResources.map((r) => r()) )
}
}
Another option is to define a Symbol which would expose a disposable method on a resource.
const DISPOSE_METHOD = Symbol('dispose');
interface IDisposable {
[DISPOSE_METHOD]: () => Promise<void>
}
class Database implements IDisposable {
async [DISPOSE_METHOD](): Promise<void> {
console.log('disconnecting')
}
}
let db = new Database();
db[DISPOSE_METHOD]()
Internals
class Node {
async dispose(): Promise<void> {
await Promise.all( resources.filter((r) => !!resource[DISPOSE_METHOD]) )
}
}
@moltar thank you for the input 🙏
Will update it soon. AFK
Got back from vacations and crunch :) WIP: https://github.com/molszanski/iti/pull/24
Hi @moltar.
In the latest version 0.5.0
I've added support for disposing
basic usage
import { createContainer } from "iti"
container = createContainer()
.add({ a: () => "123" })
.addDisposer({ a: () => {} })
container.get("a") === "123" // true
await container.disposeAll() // Promise<void>
async case
const container = createContainer()
.add(() => ({
dbConnection: async () => {
/** connect to db and return an instance */
},
}))
.addDisposer({
// ↓ `db` is a resolved value of a `dbConnection` token. Pretty handy
dbConnection: (db) => db.close(),
})
const db = await container.get("dbConnection")
await container.disposeAll()
You can launch a live playground on Stackblitz or check the playground repo.
I've updated the docs website too: https://itijs.org/docs/api#disposing
Thank you for your suggestion! 😊 🚀
@moltar I've tried many APIs and approaches and this seemed the most "clean" from a usage perspective.
I've played with this solution with some code of my own. Feels good. I think we stick with this API and wait for more feedback. Will close the issue. Let me know if you think it should be improved.
Thank you for you input @moltar ❤️ 🔥 🚀
A useful feature is to be able to dispose of resources from the container.
E.g. disconnect from the databases and so on.
See how Awilix did it.