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

Connection.isOpen returns false after timeout for the first connection, but always returns true for other connections resulting in no detection for OnDisconnect event for the rest connections. #388

Open
KeaganFerrao1998 opened this issue Sep 4, 2021 · 2 comments

Comments

@KeaganFerrao1998
Copy link

KeaganFerrao1998 commented Sep 4, 2021

const { WellKnownFolderName,
    Mailbox,
    FolderId,
    EventType,
    StreamingSubscriptionConnection,
    ExchangeService,
    WebCredentials,
    ExchangeVersion,
    Uri } = require("ews-javascript-api");
const { getMeetings } = require("../controllers/EWSController");

const streamConnections = [];

const setUpdateListner = async (credentials, resource_url, socket, io) => {
    console.log(`Setting update listner for EWS Stream notifications, Resource: ${resource_url}`)

    var isManualClose = false;
    var mailbox = new Mailbox(resource_url);
    var calenderFolderID = new FolderId(WellKnownFolderName.Calendar, mailbox);

    var service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
    service.Credentials = new WebCredentials(credentials.username, credentials.password);
    service.Url = new Uri(credentials.ews_url);

    try {
        let streamingSubscription = await service.SubscribeToStreamingNotifications(
            [calenderFolderID],
            EventType.Created,
            EventType.Deleted,
            EventType.Modified,
            EventType.FreeBusyChanged
        )
        let connection = new StreamingSubscriptionConnection(service, 30);

        streamConnections.push({
            socket,
            connection,
            streamingSubscription
        })

        connection.AddSubscription(streamingSubscription);

        //Send data once at startup.
        getMeetings(resource_url).then(data => io.to(socket.id).emit("calenderUpdate", data))

        connection.OnNotificationEvent.push(async (o, a) => {
            console.log(` --------------------------- Notification received for : ${resource_url} ---------------------------------`);

            let data = await getMeetings(resource_url);
            //TODO: Send Data here to clients subscribed to socket
        });

        connection.OnDisconnect.push((sender, subscriptionErrorEventArgsInstance) => {
            console.log(`subscribeStreamNotification: Disconnected for ${resource_url}`);      
console.log(`subscribeStreamNotification: Disconnected for ${resource_url}`);

        // If the connection was closed manually by the programmer, do not open the connection again. 
        if (isManualClose === false) {
            try {
                sender.Open();
                console.log(`subscribeStreamNotification: Connected for ${resource_url}`);
            }
            catch (error) {
                console.log("Connection already Open.", error)
            }
        }
        })

        connection.OnSubscriptionError.push((a,o) => {
            console.error(`subscribeStreamNotification: Subscription Error Occured for ${resource_url}`, o.Exception.Message);
        })

        connection.Open();

        socket.on("disconnect", async () => {
            console.log(`Socket connection for resource --${resource_url}-- is disconnected, SocketID: ${socket.id}`);
            try {
                isManualClose = true;
                connection.Close();
                console.log("Stream Connection Closed.");
            }
            catch (error) {
                console.log(`Connection ${socket.id} already closed.`)
            }

            connection.RemoveSubscription(streamingSubscription);
            await streamingSubscription.Unsubscribe();
            console.log("Stream Subscription removed.");

            connection.Dispose();
            console.log("Stream connection disposed.");
        })

        //Check connection status every status
        setInterval(() => {
            console.log(connection.IsOpen + " for " + resource_url)
        }, 10000);
    }
    catch (error) {
        console.log(`Error in try block for ${resource_url}`, error)
    }
}

module.exports = {
    setUpdateListner,
    streamConnections
}

Code Explanation: - Here "setUpdateListner" function is called on every socket connection made by different client side applications, each using different mailboxes and data is sent to clients on notification event for their specific calendar events. After the timeout of 30 mins, the connection is opened again for each client and the process continues.

ISSUE: "setInterval" is used to check the connection status of each separate connection made. It prints TRUE for all connections until the timeout of 30 mins. After 30 mins it should ideally print FALSE for all the different connections made by clients. BUT, it prints FALSE only for the first connection made by client to the server, and for all the rest connections, "connection.IsOpen" always prints TRUE, resulting in the ONDICONNECT event not triggering and connection not reconnecting for the rest.

@gautamsi
Copy link
Owner

gautamsi commented Sep 5, 2021

are you able to debug further and point out which code block may be problematic? a PR may be helpful.

@KeaganFerrao1998
Copy link
Author

KeaganFerrao1998 commented Sep 5, 2021

connection.OnDisconnect.push((sender, subscriptionErrorEventArgsInstance) => {
console.log(subscribeStreamNotification: Disconnected for ${resource_url});
console.log(subscribeStreamNotification: Disconnected for ${resource_url});

    // If the connection was closed manually by the programmer, do not open the connection again. 
    if (isManualClose === false) {
        try {
            sender.Open();
            console.log(`subscribeStreamNotification: Connected for ${resource_url}`);
        }
        catch (error) {
            console.log("Connection already Open.", error)
        }
    }
    })

The connection.OnDisconnect is only triggered for the first connection I make, and not for the rest.
I printed the connection status for each connection and found that the other connections don't show a FASLE value for connection.IsOpen property, only the first connection I make does. It is always TRUE hence OnDisconnect not trigerring

setInterval(() => {
console.log(connection.IsOpen + " for " + resource_url)
}, 10000);

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