private static async Task LoadStateAsync()

in sources/Google.Solutions.IapDesktop.Core/ResourceModel/ProjectWorkspace.cs [127:284]


        private static async Task<State> LoadStateAsync(
            IProjectWorkspaceSettings context,
            IAncestryCache ancestryCache,
            IResourceManagerClient resourceManager,
            CancellationToken cancellationToken)
        {
            //
            // NB. The Compute Engine project.get resource does not include the
            // project name, so we have to use the Resource Manager API instead.
            //
            var getProjectTasks = context
                .Projects
                .EnsureNotNull()
                .Select(p => new {
                    Locator = p,
                    Task = resourceManager.GetProjectAsync(p, cancellationToken)
                })
                .ToList();

            var projects = new List<ProjectWithAncestry>();

            foreach (var task in getProjectTasks)
            {
                //
                // NB. Some projects might not be accessible anymore,
                // either because they have been deleted or the user
                // lost access.
                //
                try
                {
                    var project = new ProjectWithAncestry(task.Locator)
                    {
                        CrmProject = await task.Task.ConfigureAwait(false)
                    };
                    projects.Add(project);

                    //
                    // Add cached ancestry, if available.
                    //
                    ancestryCache.TryGetAncestry(project.Locator, out project.OrganizationLocator);

                    CoreTraceSource.Log.TraceVerbose(
                        "Successfully loaded project {0}", project.Locator);
                }
                catch (Exception e) when (e.IsReauthError())
                {
                    //
                    // Propagate reauth errors so that the reauth logic kicks in.
                    //
                    throw e.Unwrap();
                }
                catch (Exception e)
                {
                    // 
                    // Add as inaccessible project and continue.
                    //
                    projects.Add(new ProjectWithAncestry(task.Locator));

                    CoreTraceSource.Log.TraceError(
                        "Failed to load project {0}: {1}",
                        task.Locator,
                        e);
                }
            }

            Debug.Assert(projects.Count == getProjectTasks.Count);

            //
            // At this point, we have all projects, but we might not know the
            // org ID for all projects yet.
            //

            var findOrgIdsTasks = projects
                .Where(p => p.IsAccessible && p.OrganizationLocator == null)
                .Select(p => new {
                    Project = p,
                    Task = resourceManager.FindOrganizationAsync(
                        p.Locator,
                        cancellationToken)
                })
                .ToList();

            foreach (var task in findOrgIdsTasks)
            {
                //
                // Amend ancestry (if available).
                //
                task.Project.OrganizationLocator = await task.Task.ConfigureAwait(false);

                if (task.Project.OrganizationLocator != null)
                {
                    //
                    // Cache ancestry information to speed up future lookups.
                    //
                    ancestryCache.SetAncestry(task.Project.Locator, task.Project.OrganizationLocator);
                }
            }

            //
            // Finally, resolve all org IDs.
            //
            var findOrgTasks = projects
                .Where(p => p.OrganizationLocator != null)
                .Select(p => p.OrganizationLocator)
                .Distinct()
                .Select(loc => new {
                    Organization = loc!,
                    Task = resourceManager.GetOrganizationAsync(loc!, cancellationToken)
                })
                .ToList();

            var organizations = new Dictionary<OrganizationLocator, Organization>();
            foreach (var task in findOrgTasks)
            {
                try
                {
                    var org = await task.Task.ConfigureAwait(false);
                    organizations[task.Organization] = new Organization(
                        task.Organization,
                        org.DisplayName);
                }
                catch (Exception e) when (e.IsReauthError())
                {
                    //
                    // Propagate reauth errors so that the reauth logic kicks in.
                    //
                    throw e.Unwrap();
                }
                catch
                {
                    //
                    // Organization inaccessible (even though we do have its ID),
                    // use default.
                    //
                    organizations[task.Organization] = Organization.Default;
                }
            }

            if (projects.Any(p => p.OrganizationLocator == null))
            {
                //
                // Include default org.
                //
                organizations[Organization.Default.Locator] = Organization.Default;
            }

            return new State(
                organizations,
                projects.ToDictionary(
                    p => p.Locator,
                    p => new Project(
                        p.OrganizationLocator ?? Organization.Default.Locator,
                        p.Locator,
                        p.CrmProject != null
                            ? p.CrmProject.Name // Actual name.
                            : p.Locator.Name,   // Project inaccessible, use ID.
                        p.CrmProject != null)));
        }