<commit_before>//
//  index.swift
//  Patron
//
//  Created by <NAME> on 22/11/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation
import os.log

// MARK: API

public enum PatronError: Error {
  case invalidJSON
  case invalidURL(String, [URLQueryItem]?)
}

/// Defines a JSON HTTP client.
public protocol JSONService {

  @discardableResult func get(
    path: String,
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) -> URLSessionTask

  @discardableResult func get(
    path: String,
    with query: [URLQueryItem],
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) throws -> URLSessionTask

  @discardableResult func post(
    path: String,
    json: AnyObject,
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) throws -> URLSessionTask

  @discardableResult func get(
    path: String,
    allowsCellularAccess: Bool,
    cachePolicy: URLRequest.CachePolicy,
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) -> URLSessionTask

  var host: String { get }

  /// The last `URL` or `JSONSerialization` error code, and the timestamp of
  /// its occurrence in seconds since `00:00:00 UTC on 1 January 1970`. The
  /// next successful request resets `status` to `nil`.
  var status: (Int, TimeInterval)? { get }
}

// MARK: -

/// The `Patron` class is a convenient way to represent a remote HTTP JSON
/// service endpoint. A `Patron` object provides access to a single service
/// on a specific host via `GET` and `POST` HTTP methods. It assumes that
/// payloads in both directions are JSON.
///
/// As `Patron` serializes JSON payloads on the calling thread, it is not the
/// best idea to use it from the main thread, instead, it is intended to run
/// within an `Operation` or a closure, off the main thread, encapsulating
/// request, response, and serialization.
public final class Patron: JSONService {

  fileprivate let baseURL: URL

  private let session: URLSession

  private let log: OSLog

  /// The hostname of the remote service.
  public var host: String { get { return baseURL.host! } }
  
  private let sQueue = DispatchQueue(label: "ink.codes.patron-\(UUID().uuidString)")
  
  private var _status: (Int, TimeInterval)?

  public var status: (Int, TimeInterval)? {
    get {
      return sQueue.sync {
        return _status
      }
    }
    set {
      sQueue.sync {
        _status = newValue
      }
    }
  }

  /// Creates a client for the service at the provided URL.
  ///
  /// - Parameters:
  ///   - URL: The URL of the service.
  ///   - session: The session to use for HTTP requests.
  ///   - log: The log to use, the shared disabled log by default.
  ///<commit_msg>Use global concurrent queue for serial queue<commit_after>//
//  index.swift
//  Patron
//
//  Created by <NAME> on 22/11/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation
import os.log

// MARK: API

public enum PatronError: Error {
  case invalidJSON
  case invalidURL(String, [URLQueryItem]?)
}

/// Defines a JSON HTTP client.
public protocol JSONService {

  @discardableResult func get(
    path: String,
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) -> URLSessionTask

  @discardableResult func get(
    path: String,
    with query: [URLQueryItem],
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) throws -> URLSessionTask

  @discardableResult func post(
    path: String,
    json: AnyObject,
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) throws -> URLSessionTask

  @discardableResult func get(
    path: String,
    allowsCellularAccess: Bool,
    cachePolicy: URLRequest.CachePolicy,
    cb: @escaping (AnyObject?, URLResponse?, Error?) -> Void
  ) -> URLSessionTask

  var host: String { get }

  /// The last `URL` or `JSONSerialization` error code, and the timestamp of
  /// its occurrence in seconds since `00:00:00 UTC on 1 January 1970`. The
  /// next successful request resets `status` to `nil`.
  var status: (Int, TimeInterval)? { get }
}

// MARK: -

/// The `Patron` class is a convenient way to represent a remote HTTP JSON
/// service endpoint. A `Patron` object provides access to a single service
/// on a specific host via `GET` and `POST` HTTP methods. It assumes that
/// payloads in both directions are JSON.
///
/// As `Patron` serializes JSON payloads on the calling thread, it is not the
/// best idea to use it from the main thread, instead, it is intended to run
/// within an `Operation` or a closure, off the main thread, encapsulating
/// request, response, and serialization.
public final class Patron: JSONService {

  fileprivate let baseURL: URL

  private let session: URLSession

  private let log: OSLog

  /// The hostname of the remote service.
  public var host: String { get { return baseURL.host! } }
  
  private let sQueue = DispatchQueue(
    label: "ink.codes.patron-\(UUID().uuidString)",
    target: .global()
  )
  
  private var _status: (Int, TimeInterval)?

  public var status: (Int, TimeInterval)? {
    get {
      return sQueue.sync {
        return _status
      }
    }
    set {
      sQueue.sync {
        _status = newValue
      }
    }
  }

  /// Creates a client for the service at the provided URL.
  ///
  /// - Parameters:
  ///   - URL: The URL of the service.
  ///   - session: The session to use for HTTP requests.
  ///   - log: The log to use, the shared disabled log by default.
  ///
{'fraction_non_alphanumeric': 0.11346083118793675, 'fraction_numerical': 0.007723427730783376, 'mean_word_length': 2.7981843575418996, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 23, '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': '3467665', 'n_tokens_mistral': 1673, 'n_tokens_neox': 1591, 'n_words': 635}