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

No way to gracefull exit async workers #37

Open
chsasank opened this issue May 24, 2022 · 5 comments
Open

No way to gracefull exit async workers #37

chsasank opened this issue May 24, 2022 · 5 comments

Comments

@chsasank
Copy link

There's no easy way to unref or cancel async workers such as startStoreScp. While shutDownSCU exists, it only works if storeOnly is false. Is there a better way to exit all dcmtk workers on exit?

@knopkem
Copy link
Owner

knopkem commented May 24, 2022

Hi, the current implementation via shutDownScu does not use cancel of running threads but rather waits for them to finish (thread join) there last task, which is normally what you want. But Indeed this might not work for storeOnly set to true (as this uses the old dcmtk implementation - will have a look at this). The only problematic async worker is storeSCP as it runs forever (except when receiving shutDownScu), all other works should stop after their task (e.g. CFind looking up data, C-Get loading data...) Long running C-Get or Move operations could be canceled from outside via C-Cancel requests (although DCMTK supports this, I haven't tested it with this code). Maybe you could describe your workflow and use case, so I can know what to focus on?

@YGuiraut
Copy link

YGuiraut commented Sep 20, 2022

Hi,
I am in the same situation where I would like to handle all store commands through the startStoreScp callback (so with storeOnly set to true), and still gracefully exit this process through shutdownScu.
If there is any workaround, this would be great !

@pm98zz-c
Copy link

pm98zz-c commented Jul 5, 2023

Same here. I use storescp in a Electron app with storeOnly set to true, but it prevents the whole app from exiting.
So far my options seem to be either:

  • faff around with peering to actually use storeOnly false but in reality act the same as if it were true (not even sure that would work)
  • bypass this lib enterly and instead embed and call the dcmtk "storescp" binary directly via childProcess
    Anyone came up with a workaround, by chance ?

@knopkem
Copy link
Owner

knopkem commented Jul 5, 2023

Hi, last time I tried to use the addon in electron I failed bundling it correctly, so seems you have it working. (If you have some pointers/examples how to do this I would be interested).
Regarding the shutdown process. The storeOnly flag was actually done on special request (by a different project) and uses a different control flow (which is why e.g. shutdownScu doesn't work). So I see 2 ways:
1). Implement a custom factory that uses the same code as the server with FindSCP but implements only store (without db).
2). Add the code to quit when receiving the private SOPClassUID.

While 1 would be better it might be quite some work. The relevant code part for 2 is this:

image

So, will try to do 1 and fallback to 2 in case of issues. (PRs would also be welcome if you've got the experience to do it)
Cheers

@pm98zz-c
Copy link

pm98zz-c commented Jul 5, 2023

Thanks for the pointers, it's now more clear to me why StoreSCP behaves that differently.
Regarding using it in Electron, I haven't done anything special, it "just worked". Now, this in in a legacy project I inherited that doesn't use typescript nor modern imports (and I couldn't be bothered porting it), so it could be why it turned out easy in my case.
At heart, all I do is inline with your examples (simplified below, obv). Of relevance is the fact I'm operating in the main process, not the renderer.

const { startStoreScp } = require('dicom-dimse-native')
const scpOptions = {
    source: {
        aet: 'XXX',
        ip: '127.0.0.1',
        port: 9999,
    },
    storagePath: '/tmp',
    writeTransfer: '',
    permissive: false,
    verbose: false,
    storeOnly: true,
    writeFile: false,
}
const startListener = (bunchOfExternalOptions, callback) => { 
startStoreScp(scpOptions, result => {
        const msg = JSON.parse(result)
        if (msg.message === 'BUFFER_STORAGE') {
            const buff = Buffer.from(msg.container.base64, 'base64')
            // Process data.
            const resultAsFhirResource = myParsingFunc(buff, bunchOfExternalOptions)
            callback(resultAsFhirResource)
        } else {
            console.log(msg)
        }
    })
}

I'm going to have a look at the options you pointed at, and see if I can come up with something.
Thanks !

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

4 participants