async Task UpdateReportedPropertiesWithStoreSupportAsync()

in edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/TwinManager.cs [583:662]


        async Task UpdateReportedPropertiesWithStoreSupportAsync(string id, IMessage reportedProperties)
        {
            try
            {
                using (await this.reportedPropertiesLock.LockAsync())
                {
                    bool updatePatch;
                    bool cloudVerified = false;
                    IEntityStore<string, TwinInfo> twinStore = this.TwinStore.Expect(() => new InvalidOperationException("Missing twin store"));

                    Option<TwinInfo> info = await twinStore.Get(id);
                    // If the reported properties patch is not null, we will not attempt to write the reported
                    // properties to the cloud as we are still waiting for a connection established callback
                    // to sync the local reported properties with that of the cloud
                    updatePatch = info.Map(
                        (ti) =>
                        {
                            if (ti.ReportedPropertiesPatch.Count != 0)
                            {
                                Events.NeedsUpdateCachedReportedPropertiesPatch(id, ti.ReportedPropertiesPatch.Version);
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }).GetOrElse(false);

                    TwinCollection reported = this.twinCollectionConverter.FromMessage(reportedProperties);

                    if (!updatePatch)
                    {
                        try
                        {
                            await this.SendReportedPropertiesToCloudProxy(id, reportedProperties);
                            Events.SentReportedPropertiesToCloud(id, reported.Version);
                            cloudVerified = true;
                        }
                        catch (Exception e)
                        {
                            Events.UpdateReportedToCloudException(id, e);
                            updatePatch = true;
                        }
                    }

                    if (!cloudVerified)
                    {
                        ValidateTwinProperties(JToken.Parse(reported.ToJson()), 1);
                        Events.ValidatedTwinPropertiesSuccess(id, reported.Version);
                    }

                    // Update the local twin's reported properties and swallow the exception if we failed
                    // to cache the twin
                    try
                    {
                        await this.ExecuteOnTwinStoreResultAsync(
                            id,
                            (t) => this.UpdateReportedPropertiesWhenTwinStoreHasTwinAsync(id, reported, cloudVerified),
                            () => this.UpdateReportedPropertiesWhenTwinStoreNeedsTwinAsync(id, reported, cloudVerified));
                    }
                    catch (TwinNotFoundException)
                    {
                    }

                    if (updatePatch)
                    {
                        // Update the collective patch of reported properties
                        await this.UpdateReportedPropertiesPatchAsync(
                            id,
                            new TwinInfo(null, reported) /* only used when twin was not previously cached */,
                            reported);
                    }
                }
            }
            catch (Exception e)
            {
                Events.UpdateReportedPropertiesFailed(id, e);
                throw; /* we only throw if we were unable to write to the db */
            }
        }