<commit_before>import { Account } from '../../models/account'
import { AccountsStore } from './accounts-store'
import { GitHubRepository } from '../../models/github-repository'
import { API, IAPIRefStatus } from '../api'
import { IDisposable, Disposable } from 'event-kit'
import pLimit from 'p-limit'
import { remote, ipcRenderer } from 'electron'

interface ICommitStatusCacheEntry {
  readonly status: IAPIRefStatus | null
  readonly fetchedAt: Date
}

export type StatusCallBack = (status: IAPIRefStatus | null) => void

interface IRefStatusSubscription {
  readonly endpoint: string
  readonly owner: string
  readonly name: string
  readonly ref: string
  readonly callbacks: Set<StatusCallBack>
}

function getCacheKey(repository: GitHubRepository, ref: string) {
  const { endpoint, owner, name } = repository
  return getCacheKeyForRef(endpoint, owner.login, name, ref)
}

function getCacheKeyForRef(
  endpoint: string,
  owner: string,
  name: string,
  ref: string
) {
  return `${endpoint}/repos/${owner}/${name}/commits/${ref}/status`
}

function entryIsEligibleForRefresh(entry: ICommitStatusCacheEntry) {
  const elapsed = Date.now() - entry.fetchedAt.valueOf()
  return elapsed > 60 * 1000
}

const BackgroundRefreshInterval = 60 * 1000

export class CommitStatusStore {
  private accounts: ReadonlyArray<Account> = []

  private backgroundRefreshHandle: number | null = null
  private refreshQueued = false

  private readonly subscriptions = new Map<string, IRefStatusSubscription>()
  private readonly cache = new Map<string, ICommitStatusCacheEntry>()
  private readonly queue = new Map<string, Promise<void>>()
  private readonly limit = pLimit(5)

  public constructor(accountsStore: AccountsStore) {
    accountsStore.getAll().then(accounts => (this.accounts = accounts))
    accountsStore.onDidUpdate(accounts => (this.accounts = accounts))

    ipcRenderer.on('focus', () => {
      this.startBackgroundRefresh()
      this.queueRefresh()
    })

    ipcRenderer.on('blur', () => this.stopBackgroundRefresh())

    if (remote.getCurrentWindow().isFocused()) {
      this.startBackgroundRefresh()
    }
  }

  private startBackgroundRefresh() {
    if (this.backgroundRefreshHandle === null) {
      console.log('starting background refresh')
      this.backgroundRefreshHandle = window.setInterval(
        () => this.queueRefresh(),
        BackgroundRefreshInterval
      )
    }
  }

  private stopBackgroundRefresh() {
    if (this.backgroundRefreshHandle !== null) {
      console.log('stopping background refresh')
      window.clearInterval(this.backgroundRefreshHandle)
      this.backgroundRefreshHandle = null
    }
  }

  private queueRefresh() {
    if (!this.refreshQueued) {
      this.refreshQueued = true
      setImmediate(() => {
        this.refreshQueued = false
        this.refreshEligibleSubscriptions()
      })
    }
  }

  private async refreshEligibleSubscriptions() {
    for (const key of this.subscriptions.keys()) {
      // Is it already being worked on?
      if (this.queue.has(key)) {<commit_msg>:fire: debug<commit_after>import { Account } from '../../models/account'
import { AccountsStore } from './accounts-store'
import { GitHubRepository } from '../../models/github-repository'
import { API, IAPIRefStatus } from '../api'
import { IDisposable, Disposable } from 'event-kit'
import pLimit from 'p-limit'
import { remote, ipcRenderer } from 'electron'

interface ICommitStatusCacheEntry {
  readonly status: IAPIRefStatus | null
  readonly fetchedAt: Date
}

export type StatusCallBack = (status: IAPIRefStatus | null) => void

interface IRefStatusSubscription {
  readonly endpoint: string
  readonly owner: string
  readonly name: string
  readonly ref: string
  readonly callbacks: Set<StatusCallBack>
}

function getCacheKey(repository: GitHubRepository, ref: string) {
  const { endpoint, owner, name } = repository
  return getCacheKeyForRef(endpoint, owner.login, name, ref)
}

function getCacheKeyForRef(
  endpoint: string,
  owner: string,
  name: string,
  ref: string
) {
  return `${endpoint}/repos/${owner}/${name}/commits/${ref}/status`
}

function entryIsEligibleForRefresh(entry: ICommitStatusCacheEntry) {
  const elapsed = Date.now() - entry.fetchedAt.valueOf()
  return elapsed > 60 * 1000
}

const BackgroundRefreshInterval = 60 * 1000

export class CommitStatusStore {
  private accounts: ReadonlyArray<Account> = []

  private backgroundRefreshHandle: number | null = null
  private refreshQueued = false

  private readonly subscriptions = new Map<string, IRefStatusSubscription>()
  private readonly cache = new Map<string, ICommitStatusCacheEntry>()
  private readonly queue = new Map<string, Promise<void>>()
  private readonly limit = pLimit(5)

  public constructor(accountsStore: AccountsStore) {
    accountsStore.getAll().then(accounts => (this.accounts = accounts))
    accountsStore.onDidUpdate(accounts => (this.accounts = accounts))

    ipcRenderer.on('focus', () => {
      this.startBackgroundRefresh()
      this.queueRefresh()
    })

    ipcRenderer.on('blur', () => this.stopBackgroundRefresh())

    if (remote.getCurrentWindow().isFocused()) {
      this.startBackgroundRefresh()
    }
  }

  private startBackgroundRefresh() {
    if (this.backgroundRefreshHandle === null) {
      this.backgroundRefreshHandle = window.setInterval(
        () => this.queueRefresh(),
        BackgroundRefreshInterval
      )
    }
  }

  private stopBackgroundRefresh() {
    if (this.backgroundRefreshHandle !== null) {
      window.clearInterval(this.backgroundRefreshHandle)
      this.backgroundRefreshHandle = null
    }
  }

  private queueRefresh() {
    if (!this.refreshQueued) {
      this.refreshQueued = true
      setImmediate(() => {
        this.refreshQueued = false
        this.refreshEligibleSubscriptions()
      })
    }
  }

  private async refreshEligibleSubscriptions() {
    for (const key of this.subscriptions.keys()) {
      // Is it already being worked on?
      if (this.queue.has(key)) {
{'fraction_non_alphanumeric': 0.11338320864505404, 'fraction_numerical': 0.0043225270157938485, 'mean_word_length': 3.955518945634267, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6947766', 'n_tokens_mistral': 1717, 'n_tokens_neox': 1683, 'n_words': 411}