public async Task UpsertAsync(Repository repository, DateTime?asOf) { var repositoryCurrentStateId = await repositoryCurrentStateRepository.UpsertAsync(repository.CurrentState).ConfigureAwait(false); if (repository.Snapshot != null) { // Get the commit related information for the repo at the specified point in time // Need this to properly set the window time range for which the snapshot information we are // saving is valid for var repoSourceSnapshot = await repositorySourceManager.ReadRepositorySourceSnapshotAsync(repository.CurrentState.Owner, repository.CurrentState.Name, repository.CurrentState.DefaultBranch, asOf).ConfigureAwait(false); repository.Snapshot.WindowStartCommitId = repoSourceSnapshot.ClosestCommitId; // Sometimes the pushed date is null, E.G. When a repository is renamed and the commit occured prior to the rename repository.Snapshot.WindowStartsOn = repoSourceSnapshot.ClosestCommitPushedDate ?? repoSourceSnapshot.ClosestCommitCommittedDate; // Do we really need to read all existing repository snapshots here? Could probably get away with just reading // the first one before the asOf date and the first one after the asOf date but that can be left as a future // optimization var existingSnapshots = await repositorySnapshotRepository.ReadAllForParent(repository.CurrentState.Id).ConfigureAwait(false); if (!existingSnapshots.Any()) { repository.Snapshot.WindowEndsOn = null; } else { /* * We need to figure out the following two things * * 1) When should this snapshots window end? * * If there is a snapshot with a window starting at a later date then this * later snapshots starting window time should be this snapshots ending window time * * 2) Do we need to update the window end of an existing snapshot? * * If there an existing snapshot who's end date is later than the current snapshots start date * then we need to update this existing snapshots end date */ var snapshotsWithLaterStartingDate = existingSnapshots.Where(snapshot => snapshot.WindowStartsOn > repository.Snapshot.WindowStartsOn); if (snapshotsWithLaterStartingDate.Any()) { var closestLaterStartingSnapshot = snapshotsWithLaterStartingDate.OrderBy(snapshot => snapshot.WindowStartsOn).First(); repository.Snapshot.WindowEndsOn = closestLaterStartingSnapshot.WindowStartsOn.Value.AddTicks(-1); } var snapshotsWithEarlierStartingDate = existingSnapshots.Where(snapshot => snapshot.WindowStartsOn < repository.Snapshot.WindowStartsOn); if (snapshotsWithEarlierStartingDate.Any()) { var closestEarlierStartingSnapshot = snapshotsWithEarlierStartingDate.OrderByDescending(snapshot => snapshot.WindowStartsOn).First(); var newEndTime = repository.Snapshot.WindowStartsOn.Value.AddTicks(-1); closestEarlierStartingSnapshot.WindowEndsOn = repository.Snapshot.WindowStartsOn.Value.AddTicks(-1); if (closestEarlierStartingSnapshot.WindowEndsOn != newEndTime) { closestEarlierStartingSnapshot.WindowEndsOn = newEndTime; await repositorySnapshotRepository.UpsertAsync(closestEarlierStartingSnapshot, repositoryCurrentStateId).ConfigureAwait(false); } } } await repositorySnapshotRepository.UpsertAsync(repository.Snapshot, repositoryCurrentStateId).ConfigureAwait(false); } }
public async Task UpsertAsync(Repository repository, DateTime?asOf) { var repositoryCurrentStateId = await repositoryCurrentStateRepository.UpsertAsync(repository.CurrentState).ConfigureAwait(false); if (repository.Snapshot != null) { // Avoid messing with the window stuff if the repository currently has no branches // TODO: Figure out how this is going to work when a repository that is currently empty is no longer empty ... // Do we care that it was empty at one point? It save to assume that a repo will only go from empty to non empty // and not vice versa? If so we could set the window start date for this snapshot to the repo creation date if (repository.CurrentState.DefaultBranch != null) { // Get the commit related information for the repo at the specified point in time // Need this to properly set the window time range for which the snapshot information we are // saving is valid for var repoSourceSnapshot = await repositorySourceManager.ReadRepositorySourceSnapshotAsync(repository.CurrentState.Owner, repository.CurrentState.Name, repository.CurrentState.DefaultBranch, asOf).ConfigureAwait(false); repository.Snapshot.WindowStartCommitId = repoSourceSnapshot.ClosestCommitId; // Sometimes the pushed date is null, E.G. When a repository is renamed and the commit occured prior to the rename repository.Snapshot.WindowStartsOn = repoSourceSnapshot.ClosestCommitPushedDate ?? repoSourceSnapshot.ClosestCommitCommittedDate; // Do we really need to read all existing repository snapshots here? Could probably get away with just reading // the first one before the asOf date and the first one after the asOf date but that can be left as a future // optimization var existingSnapshots = await repositorySnapshotRepository.ReadAllForParent(repository.CurrentState.Id).ConfigureAwait(false); if (!existingSnapshots.Any()) { repository.Snapshot.WindowEndsOn = null; } else { /* * We need to figure out the following two things * * 1) When should this snapshots window end? * * If there is a snapshot with a window starting at a later date then this * later snapshots starting window time should be this snapshots ending window time * * 2) Do we need to update the window end of an existing snapshot? * * If there an existing snapshot who's end date is later than the current snapshots start date * then we need to update this existing snapshots end date */ var snapshotsWithLaterStartingDate = existingSnapshots.Where(snapshot => snapshot.WindowStartsOn > repository.Snapshot.WindowStartsOn); if (snapshotsWithLaterStartingDate.Any()) { var closestLaterStartingSnapshot = snapshotsWithLaterStartingDate.OrderBy(snapshot => snapshot.WindowStartsOn).First(); repository.Snapshot.WindowEndsOn = closestLaterStartingSnapshot.WindowStartsOn.Value.AddTicks(-1); } var snapshotsWithEarlierStartingDate = existingSnapshots.Where(snapshot => snapshot.WindowStartsOn < repository.Snapshot.WindowStartsOn); if (snapshotsWithEarlierStartingDate.Any()) { var closestEarlierStartingSnapshot = snapshotsWithEarlierStartingDate.OrderByDescending(snapshot => snapshot.WindowStartsOn).First(); var newEndTime = repository.Snapshot.WindowStartsOn.Value.AddTicks(-1); closestEarlierStartingSnapshot.WindowEndsOn = repository.Snapshot.WindowStartsOn.Value.AddTicks(-1); if (closestEarlierStartingSnapshot.WindowEndsOn != newEndTime) { closestEarlierStartingSnapshot.WindowEndsOn = newEndTime; await repositorySnapshotRepository.UpsertAsync(closestEarlierStartingSnapshot, repositoryCurrentStateId).ConfigureAwait(false); } } } } else { // If there isn't any branch information then set this snapshot to start now. This way it can have it's end daate set // when and if the repository does get a branch and some updated type information repository.Snapshot.WindowStartsOn = repository.Snapshot.TakenOn; } await repositorySnapshotRepository.UpsertAsync(repository.Snapshot, repositoryCurrentStateId).ConfigureAwait(false); } }