files.com 1.1.813 → 1.1.815

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. checksums.yaml +4 -4
  2. data/_VERSION +1 -1
  3. data/doc/Files/APIConnectionError.html +1 -1
  4. data/doc/Files/APIError.html +1 -1
  5. data/doc/Files/AccountAlreadyExistsError.html +1 -1
  6. data/doc/Files/AccountLineItem.html +1 -1
  7. data/doc/Files/AccountOverdueError.html +1 -1
  8. data/doc/Files/Action.html +1 -1
  9. data/doc/Files/ActionLog.html +1 -1
  10. data/doc/Files/ActionNotificationExport.html +1 -1
  11. data/doc/Files/ActionNotificationExportResult.html +1 -1
  12. data/doc/Files/AdditionalAuthenticationRequiredError.html +1 -1
  13. data/doc/Files/AgentNode.html +1 -1
  14. data/doc/Files/AgentNodeConnection.html +1 -1
  15. data/doc/Files/AgentNodeInstance.html +1 -1
  16. data/doc/Files/AgentPushUpdate.html +1 -1
  17. data/doc/Files/AgentPushUpdateBlockedError.html +1 -1
  18. data/doc/Files/AgentUnavailableError.html +1 -1
  19. data/doc/Files/AgentUpgradeRequiredError.html +1 -1
  20. data/doc/Files/AiAssistantPersonality.html +1 -1
  21. data/doc/Files/AiTask.html +1 -1
  22. data/doc/Files/AiTaskCannotBeRunManuallyError.html +1 -1
  23. data/doc/Files/AlreadyCompletedError.html +1 -1
  24. data/doc/Files/Api.html +20 -13
  25. data/doc/Files/ApiClient/RequestLogContext.html +29 -29
  26. data/doc/Files/ApiClient/TransferSettings.html +721 -0
  27. data/doc/Files/ApiClient.html +756 -204
  28. data/doc/Files/ApiKey.html +1 -1
  29. data/doc/Files/ApiKeyIsDisabledError.html +1 -1
  30. data/doc/Files/ApiKeyIsPathRestrictedError.html +1 -1
  31. data/doc/Files/ApiKeyNotFoundError.html +1 -1
  32. data/doc/Files/ApiKeyOnlyForDesktopAppError.html +1 -1
  33. data/doc/Files/ApiKeyOnlyForFileOperationsError.html +1 -1
  34. data/doc/Files/ApiKeyOnlyForMobileAppError.html +1 -1
  35. data/doc/Files/ApiKeyOnlyForOfficeIntegrationError.html +1 -1
  36. data/doc/Files/ApiKeySessionsNotSupportedError.html +1 -1
  37. data/doc/Files/ApiRequestLog.html +1 -1
  38. data/doc/Files/App.html +1 -1
  39. data/doc/Files/As2IncomingMessage.html +1 -1
  40. data/doc/Files/As2OutgoingMessage.html +1 -1
  41. data/doc/Files/As2Partner.html +1 -1
  42. data/doc/Files/As2Station.html +1 -1
  43. data/doc/Files/AttachmentTooLargeError.html +1 -1
  44. data/doc/Files/AuthenticationError.html +1 -1
  45. data/doc/Files/AuthenticationRequiredError.html +1 -1
  46. data/doc/Files/Auto.html +1 -1
  47. data/doc/Files/Automation.html +1 -1
  48. data/doc/Files/AutomationAuthoringSchema.html +1 -1
  49. data/doc/Files/AutomationCannotBeRunManuallyError.html +1 -1
  50. data/doc/Files/AutomationExecutionNode.html +1 -1
  51. data/doc/Files/AutomationLog.html +1 -1
  52. data/doc/Files/AutomationRun.html +1 -1
  53. data/doc/Files/AutomationsUnavailableError.html +1 -1
  54. data/doc/Files/BadRequestError.html +1 -1
  55. data/doc/Files/BandwidthSnapshot.html +1 -1
  56. data/doc/Files/Behavior.html +1 -1
  57. data/doc/Files/BehaviorNotAllowedOnRemoteServerError.html +1 -1
  58. data/doc/Files/BillingInformationHiddenError.html +1 -1
  59. data/doc/Files/BillingPermissionRequiredError.html +1 -1
  60. data/doc/Files/BufferedUploadDisabledForThisDestinationError.html +1 -1
  61. data/doc/Files/Bundle.html +1 -1
  62. data/doc/Files/BundleAction.html +1 -1
  63. data/doc/Files/BundleDownload.html +1 -1
  64. data/doc/Files/BundleMaximumUsesReachedError.html +1 -1
  65. data/doc/Files/BundleNotification.html +1 -1
  66. data/doc/Files/BundleOnlyAllowsPreviewsError.html +1 -1
  67. data/doc/Files/BundleOperationRequiresSubfolderError.html +1 -1
  68. data/doc/Files/BundlePath.html +1 -1
  69. data/doc/Files/BundlePathNotFoundError.html +1 -1
  70. data/doc/Files/BundlePermissionRequiredError.html +1 -1
  71. data/doc/Files/BundleRecipient.html +1 -1
  72. data/doc/Files/BundleRegistration.html +1 -1
  73. data/doc/Files/BundleRegistrationCodeFailedError.html +1 -1
  74. data/doc/Files/BundleRegistrationNotFoundError.html +1 -1
  75. data/doc/Files/CannotAdministerHigherLevelUserError.html +1 -1
  76. data/doc/Files/CannotDownloadDirectoryError.html +1 -1
  77. data/doc/Files/CannotLoginWhileUsingKeyError.html +1 -1
  78. data/doc/Files/CantActForOtherUserError.html +1 -1
  79. data/doc/Files/CantMoveWithMultipleLocationsError.html +1 -1
  80. data/doc/Files/ChatMessage.html +1 -1
  81. data/doc/Files/ChatSession.html +1 -1
  82. data/doc/Files/ChildSiteManagementPolicy.html +1 -1
  83. data/doc/Files/Clickwrap.html +1 -1
  84. data/doc/Files/CodeNotFoundError.html +1 -1
  85. data/doc/Files/ConfigurationLockedPathError.html +1 -1
  86. data/doc/Files/ContactAdminForPasswordChangeHelpError.html +1 -1
  87. data/doc/Files/CouldNotCreateParentError.html +1 -1
  88. data/doc/Files/CustomDomain.html +1 -1
  89. data/doc/Files/DatetimeParseError.html +1 -1
  90. data/doc/Files/DesktopConfigurationProfile.html +1 -1
  91. data/doc/Files/DestinationExistsError.html +1 -1
  92. data/doc/Files/DestinationFolderLimitedError.html +1 -1
  93. data/doc/Files/DestinationParentConflictError.html +1 -1
  94. data/doc/Files/DestinationParentDoesNotExistError.html +1 -1
  95. data/doc/Files/DestinationSameError.html +1 -1
  96. data/doc/Files/DestinationSiteMismatchError.html +1 -1
  97. data/doc/Files/DirectConnectionInfo.html +1 -1
  98. data/doc/Files/DnsRecord.html +1 -1
  99. data/doc/Files/DoesNotSupportSortingError.html +1 -1
  100. data/doc/Files/DuplicateShareRecipientError.html +1 -1
  101. data/doc/Files/EmailIncomingMessage.html +1 -1
  102. data/doc/Files/EmailLog.html +1 -1
  103. data/doc/Files/Error.html +2 -2
  104. data/doc/Files/Errors.html +1 -1
  105. data/doc/Files/EventChannel.html +1 -1
  106. data/doc/Files/EventDeliveryAttempt.html +1 -1
  107. data/doc/Files/EventRecord.html +1 -1
  108. data/doc/Files/EventSubscription.html +1 -1
  109. data/doc/Files/EventTarget.html +1 -1
  110. data/doc/Files/ExavaultApiRequestLog.html +1 -1
  111. data/doc/Files/ExceededRuntimeLimitError.html +1 -1
  112. data/doc/Files/Expectation.html +1 -1
  113. data/doc/Files/ExpectationAlreadyHasOpenWindowError.html +1 -1
  114. data/doc/Files/ExpectationEvaluation.html +1 -1
  115. data/doc/Files/ExpectationIncident.html +1 -1
  116. data/doc/Files/ExpectationNotManualTriggerError.html +1 -1
  117. data/doc/Files/ExpiredPrivateKeyError.html +1 -1
  118. data/doc/Files/ExpiredPublicKeyError.html +1 -1
  119. data/doc/Files/ExportFailureError.html +1 -1
  120. data/doc/Files/ExportNotReadyError.html +1 -1
  121. data/doc/Files/ExternalEvent.html +1 -1
  122. data/doc/Files/FailedToChangePasswordError.html +1 -1
  123. data/doc/Files/File.html +2019 -1515
  124. data/doc/Files/FileAction.html +1 -1
  125. data/doc/Files/FileActionError.html +1 -1
  126. data/doc/Files/FileComment.html +1 -1
  127. data/doc/Files/FileCommentReaction.html +1 -1
  128. data/doc/Files/FileLockedError.html +1 -1
  129. data/doc/Files/FileMigration.html +1 -1
  130. data/doc/Files/FileMigrationLog.html +1 -1
  131. data/doc/Files/FileNotFoundError.html +1 -1
  132. data/doc/Files/FileNotUploadedError.html +1 -1
  133. data/doc/Files/FilePendingProcessingError.html +1 -1
  134. data/doc/Files/FileProcessingErrorError.html +1 -1
  135. data/doc/Files/FileTooBigToDecryptError.html +1 -1
  136. data/doc/Files/FileTooBigToEncryptError.html +1 -1
  137. data/doc/Files/FileUploadNotFoundError.html +1 -1
  138. data/doc/Files/FileUploadPart.html +1 -1
  139. data/doc/Files/FileUploadedToWrongRegionError.html +1 -1
  140. data/doc/Files/FileUtils.html +1 -1
  141. data/doc/Files/FilenameTooLongError.html +1 -1
  142. data/doc/Files/FilesAgentFailedAuthorizationError.html +1 -1
  143. data/doc/Files/FilesNativeStorageOverloadedError.html +1 -1
  144. data/doc/Files/Folder.html +1 -1
  145. data/doc/Files/FolderAdminOrBillingPermissionRequiredError.html +1 -1
  146. data/doc/Files/FolderAdminPermissionRequiredError.html +1 -1
  147. data/doc/Files/FolderLockedError.html +1 -1
  148. data/doc/Files/FolderMustNotBeAFileError.html +1 -1
  149. data/doc/Files/FolderNotEmptyError.html +1 -1
  150. data/doc/Files/FoldersNotAllowedError.html +1 -1
  151. data/doc/Files/FormField.html +1 -1
  152. data/doc/Files/FormFieldSet.html +1 -1
  153. data/doc/Files/FtpActionLog.html +1 -1
  154. data/doc/Files/FullPermissionRequiredError.html +1 -1
  155. data/doc/Files/GpgKey.html +1 -1
  156. data/doc/Files/Group.html +1 -1
  157. data/doc/Files/GroupNotFoundError.html +1 -1
  158. data/doc/Files/GroupUser.html +1 -1
  159. data/doc/Files/History.html +1 -1
  160. data/doc/Files/HistoryExport.html +1 -1
  161. data/doc/Files/HistoryExportResult.html +1 -1
  162. data/doc/Files/HistoryPermissionRequiredError.html +1 -1
  163. data/doc/Files/HistoryUnavailableError.html +1 -1
  164. data/doc/Files/HolidayCalendar.html +1 -1
  165. data/doc/Files/HolidayRegion.html +1 -1
  166. data/doc/Files/Image.html +1 -1
  167. data/doc/Files/InAppAiAssistantUnavailableError.html +1 -1
  168. data/doc/Files/InboundS3Log.html +1 -1
  169. data/doc/Files/InboxNotFoundError.html +1 -1
  170. data/doc/Files/InboxRecipient.html +1 -1
  171. data/doc/Files/InboxRegistration.html +1 -1
  172. data/doc/Files/InboxRegistrationCodeFailedError.html +1 -1
  173. data/doc/Files/InboxUpload.html +1 -1
  174. data/doc/Files/InsufficientPermissionForParamsError.html +1 -1
  175. data/doc/Files/InsufficientPermissionForSiteError.html +1 -1
  176. data/doc/Files/IntegrationCentricProfile.html +1 -1
  177. data/doc/Files/InternalGeneralErrorError.html +1 -1
  178. data/doc/Files/InvalidBodyError.html +1 -1
  179. data/doc/Files/InvalidBundleCodeError.html +1 -1
  180. data/doc/Files/InvalidCredentialsError.html +1 -1
  181. data/doc/Files/InvalidCursorError.html +1 -1
  182. data/doc/Files/InvalidCursorTypeForSortError.html +1 -1
  183. data/doc/Files/InvalidEtagsError.html +1 -1
  184. data/doc/Files/InvalidFileTypeError.html +1 -1
  185. data/doc/Files/InvalidFilenameError.html +1 -1
  186. data/doc/Files/InvalidFilterAliasCombinationError.html +1 -1
  187. data/doc/Files/InvalidFilterFieldError.html +1 -1
  188. data/doc/Files/InvalidFilterParamError.html +1 -1
  189. data/doc/Files/InvalidFilterParamFormatError.html +1 -1
  190. data/doc/Files/InvalidFilterParamValueError.html +1 -1
  191. data/doc/Files/InvalidInputEncodingError.html +1 -1
  192. data/doc/Files/InvalidInterfaceError.html +1 -1
  193. data/doc/Files/InvalidOauthError.html +1 -1
  194. data/doc/Files/InvalidOauthProviderError.html +1 -1
  195. data/doc/Files/InvalidOrExpiredCodeError.html +1 -1
  196. data/doc/Files/InvalidParameterError.html +5 -1
  197. data/doc/Files/InvalidPathError.html +1 -1
  198. data/doc/Files/InvalidPriorityColorError.html +1 -1
  199. data/doc/Files/InvalidRangeError.html +1 -1
  200. data/doc/Files/InvalidReturnToUrlError.html +1 -1
  201. data/doc/Files/InvalidSearchQueryError.html +1 -1
  202. data/doc/Files/InvalidSessionError.html +1 -1
  203. data/doc/Files/InvalidSiteError.html +1 -1
  204. data/doc/Files/InvalidSortFieldError.html +1 -1
  205. data/doc/Files/InvalidSortFilterCombinationError.html +1 -1
  206. data/doc/Files/InvalidUploadOffsetError.html +1 -1
  207. data/doc/Files/InvalidUploadPartGapError.html +1 -1
  208. data/doc/Files/InvalidUploadPartSizeError.html +1 -1
  209. data/doc/Files/InvalidUsernameOrPasswordError.html +1 -1
  210. data/doc/Files/InvalidWorkspaceIdHeaderError.html +1 -1
  211. data/doc/Files/InvalidZipFileError.html +1 -1
  212. data/doc/Files/Invoice.html +1 -1
  213. data/doc/Files/InvoiceLineItem.html +1 -1
  214. data/doc/Files/IpAddress.html +1 -1
  215. data/doc/Files/KeyLifecycleRule.html +1 -1
  216. data/doc/Files/List.html +1 -1
  217. data/doc/Files/Lock.html +1 -1
  218. data/doc/Files/LockOperationBusyError.html +1 -1
  219. data/doc/Files/LockedOutError.html +1 -1
  220. data/doc/Files/LockoutRegionMismatchError.html +1 -1
  221. data/doc/Files/MetadataCategory.html +1 -1
  222. data/doc/Files/MetadataNotSupportedOnRemotesError.html +1 -1
  223. data/doc/Files/MethodNotAllowedError.html +1 -1
  224. data/doc/Files/MigrationInProgressError.html +1 -1
  225. data/doc/Files/MissingParameterError.html +1 -1
  226. data/doc/Files/ModelSaveErrorError.html +1 -1
  227. data/doc/Files/MoverAccessDeniedError.html +1 -1
  228. data/doc/Files/MoverPackageRequiredError.html +1 -1
  229. data/doc/Files/MultipleProcessingErrorsError.html +1 -1
  230. data/doc/Files/MultipleSortParamsNotAllowedError.html +1 -1
  231. data/doc/Files/MustAuthenticateWithApiKeyError.html +1 -1
  232. data/doc/Files/NeedAdminPermissionForInboxError.html +1 -1
  233. data/doc/Files/NestedNotFoundError.html +1 -1
  234. data/doc/Files/NoAccountForSiteError.html +1 -1
  235. data/doc/Files/NoValidInputParamsError.html +1 -1
  236. data/doc/Files/NonAdminsMustQueryByFolderOrPathError.html +1 -1
  237. data/doc/Files/NotAllowedToCreateBundleError.html +1 -1
  238. data/doc/Files/NotAuthenticatedError.html +1 -1
  239. data/doc/Files/NotAuthorizedError.html +1 -1
  240. data/doc/Files/NotEnqueuableSyncError.html +1 -1
  241. data/doc/Files/NotFoundError.html +1 -1
  242. data/doc/Files/NotImplementedError.html +1 -1
  243. data/doc/Files/Notification.html +1 -1
  244. data/doc/Files/OffsetUploadNotAllowedWithMalwareScanningError.html +1 -1
  245. data/doc/Files/OneTimePasswordIncorrectError.html +1 -1
  246. data/doc/Files/OutboundConnectionLog.html +1 -1
  247. data/doc/Files/PartNumberTooLargeError.html +1 -1
  248. data/doc/Files/Partner.html +1 -1
  249. data/doc/Files/PartnerChannel.html +1 -1
  250. data/doc/Files/PartnerChannelTemplate.html +1 -1
  251. data/doc/Files/PartnerConnection.html +1 -1
  252. data/doc/Files/PartnerSite.html +1 -1
  253. data/doc/Files/PartnerSiteRequest.html +1 -1
  254. data/doc/Files/PasswordChangeNotRequiredError.html +1 -1
  255. data/doc/Files/PasswordChangeRequiredError.html +1 -1
  256. data/doc/Files/PathCannotHaveTrailingWhitespaceError.html +1 -1
  257. data/doc/Files/PathTooLongError.html +1 -1
  258. data/doc/Files/PathUtil.html +1 -1
  259. data/doc/Files/Payment.html +1 -1
  260. data/doc/Files/PaymentLineItem.html +1 -1
  261. data/doc/Files/PaymentMethodErrorError.html +1 -1
  262. data/doc/Files/PendingWorkEvent.html +1 -1
  263. data/doc/Files/Permission.html +1 -1
  264. data/doc/Files/PlanNotFoundError.html +1 -1
  265. data/doc/Files/Preview.html +1 -1
  266. data/doc/Files/PreviewOnlyPermissionCannotDownloadError.html +1 -1
  267. data/doc/Files/ProcessingFailureError.html +1 -1
  268. data/doc/Files/PublicHostingRequestLog.html +1 -1
  269. data/doc/Files/PublicIpAddress.html +1 -1
  270. data/doc/Files/PublicKey.html +1 -1
  271. data/doc/Files/RateLimitedError.html +1 -1
  272. data/doc/Files/ReadOnlySessionError.html +1 -1
  273. data/doc/Files/ReadPermissionRequiredError.html +1 -1
  274. data/doc/Files/ReauthenticationFailedError.html +1 -1
  275. data/doc/Files/ReauthenticationFailedFinalError.html +1 -1
  276. data/doc/Files/ReauthenticationNeededActionError.html +1 -1
  277. data/doc/Files/ReauthenticationNeededFieldsError.html +1 -1
  278. data/doc/Files/ReauthenticationRateLimitedError.html +1 -1
  279. data/doc/Files/RecaptchaFailedError.html +1 -1
  280. data/doc/Files/RecipientAlreadySharedError.html +1 -1
  281. data/doc/Files/RemoteBandwidthSnapshot.html +1 -1
  282. data/doc/Files/RemoteDesktopDebugLoggingDisabledError.html +1 -1
  283. data/doc/Files/RemoteEntryReadOnlyError.html +1 -1
  284. data/doc/Files/RemoteMountBackend.html +1 -1
  285. data/doc/Files/RemoteServer.html +1 -1
  286. data/doc/Files/RemoteServerConfigurationFile.html +1 -1
  287. data/doc/Files/RemoteServerCredential.html +1 -1
  288. data/doc/Files/RemoteServerErrorError.html +1 -1
  289. data/doc/Files/Request.html +1 -1
  290. data/doc/Files/RequestBodyTooLargeError.html +1 -1
  291. data/doc/Files/RequestParamsContainInvalidCharacterError.html +1 -1
  292. data/doc/Files/RequestParamsInvalidError.html +1 -1
  293. data/doc/Files/RequestParamsRequiredError.html +1 -1
  294. data/doc/Files/ResourceBelongsToParentSiteError.html +1 -1
  295. data/doc/Files/ResourceLockedError.html +1 -1
  296. data/doc/Files/Response.html +1 -1
  297. data/doc/Files/Restore.html +1 -1
  298. data/doc/Files/RootFolderBehaviorSiteAdminRequiredError.html +1 -1
  299. data/doc/Files/RootFolderBehaviorSkipSiteAdminRequiredError.html +1 -1
  300. data/doc/Files/Schedule.html +1 -1
  301. data/doc/Files/ScheduledExport.html +1 -1
  302. data/doc/Files/ScimLog.html +1 -1
  303. data/doc/Files/SearchAllOnChildPathError.html +1 -1
  304. data/doc/Files/SearchUnavailableError.html +1 -1
  305. data/doc/Files/Secret.html +1 -1
  306. data/doc/Files/SelfManagedRequiredError.html +1 -1
  307. data/doc/Files/ServiceUnavailableError.html +1 -1
  308. data/doc/Files/Session.html +1 -1
  309. data/doc/Files/SettingsChange.html +1 -1
  310. data/doc/Files/SftpActionLog.html +1 -1
  311. data/doc/Files/SftpHostKey.html +1 -1
  312. data/doc/Files/ShareGroup.html +1 -1
  313. data/doc/Files/ShareGroupMember.html +1 -1
  314. data/doc/Files/SiemHttpDestination.html +1 -1
  315. data/doc/Files/SiemHttpDestinationEvent.html +1 -1
  316. data/doc/Files/Site.html +911 -731
  317. data/doc/Files/SiteAdminOrPartnerAdminPermissionRequiredError.html +1 -1
  318. data/doc/Files/SiteAdminOrWorkspaceAdminOrFolderAdminPermissionRequiredError.html +1 -1
  319. data/doc/Files/SiteAdminOrWorkspaceAdminOrPartnerAdminOrFolderAdminPermissionRequiredError.html +1 -1
  320. data/doc/Files/SiteAdminOrWorkspaceAdminOrPartnerAdminPermissionRequiredError.html +1 -1
  321. data/doc/Files/SiteAdminOrWorkspaceAdminPermissionRequiredError.html +1 -1
  322. data/doc/Files/SiteAdminRequiredError.html +1 -1
  323. data/doc/Files/SiteConfigurationError.html +1 -1
  324. data/doc/Files/SiteDisabledError.html +1 -1
  325. data/doc/Files/SiteFilesAreImmutableError.html +1 -1
  326. data/doc/Files/SiteNotFoundError.html +1 -1
  327. data/doc/Files/SiteSubdomainRedirect.html +1 -1
  328. data/doc/Files/SiteWasRemovedError.html +1 -1
  329. data/doc/Files/SizableIO.html +1 -1
  330. data/doc/Files/Snapshot.html +1 -1
  331. data/doc/Files/SsoEvent.html +1 -1
  332. data/doc/Files/SsoStrategy.html +1 -1
  333. data/doc/Files/Status.html +1 -1
  334. data/doc/Files/Style.html +1 -1
  335. data/doc/Files/SubfolderLockedError.html +1 -1
  336. data/doc/Files/Sync.html +1 -1
  337. data/doc/Files/SyncInProgressError.html +1 -1
  338. data/doc/Files/SyncLog.html +1 -1
  339. data/doc/Files/SyncRun.html +1 -1
  340. data/doc/Files/SyncRunLiveTransfer.html +1 -1
  341. data/doc/Files/SystemProfiler.html +1 -1
  342. data/doc/Files/TooManyConcurrentLoginsError.html +1 -1
  343. data/doc/Files/TooManyConcurrentRequestsError.html +1 -1
  344. data/doc/Files/TooManyLoginAttemptsError.html +1 -1
  345. data/doc/Files/TooManyRequestsError.html +1 -1
  346. data/doc/Files/TooManySharesError.html +1 -1
  347. data/doc/Files/Transfer/BufferLimitError.html +175 -0
  348. data/doc/Files/Transfer/ByteBudget/Reservation.html +301 -0
  349. data/doc/Files/Transfer/ByteBudget.html +748 -0
  350. data/doc/Files/Transfer/CancelledError.html +235 -0
  351. data/doc/Files/Transfer/Checkpoint.html +1371 -0
  352. data/doc/Files/Transfer/CheckpointError.html +173 -0
  353. data/doc/Files/Transfer/ClientTransport/ClientResponse.html +661 -0
  354. data/doc/Files/Transfer/ClientTransport/Reader.html +530 -0
  355. data/doc/Files/Transfer/ClientTransport.html +675 -0
  356. data/doc/Files/Transfer/Clock.html +189 -0
  357. data/doc/Files/Transfer/Control.html +667 -0
  358. data/doc/Files/Transfer/Controller/Attempt.html +465 -0
  359. data/doc/Files/Transfer/Controller.html +1166 -0
  360. data/doc/Files/Transfer/Coordinator/Timing.html +568 -0
  361. data/doc/Files/Transfer/Coordinator.html +534 -0
  362. data/doc/Files/Transfer/DownloadCoordinator/FileSink.html +976 -0
  363. data/doc/Files/Transfer/DownloadCoordinator/IoSink.html +1168 -0
  364. data/doc/Files/Transfer/DownloadCoordinator/Piece.html +875 -0
  365. data/doc/Files/Transfer/DownloadCoordinator.html +728 -0
  366. data/doc/Files/Transfer/FileSlots.html +480 -0
  367. data/doc/Files/Transfer/FrontendResponseError.html +235 -0
  368. data/doc/Files/Transfer/Holds.html +505 -0
  369. data/doc/Files/Transfer/HttpTransport.html +579 -0
  370. data/doc/Files/Transfer/Job.html +2338 -0
  371. data/doc/Files/Transfer/Options.html +924 -0
  372. data/doc/Files/Transfer/PausedError.html +319 -0
  373. data/doc/Files/Transfer/Policy.html +1642 -0
  374. data/doc/Files/Transfer/RequestPermits.html +160 -0
  375. data/doc/Files/Transfer/SourceChangedError.html +235 -0
  376. data/doc/Files/Transfer/StorageResponse.html +546 -0
  377. data/doc/Files/Transfer/StorageRetry.html +1098 -0
  378. data/doc/Files/Transfer/UploadCoordinator/Grant.html +1048 -0
  379. data/doc/Files/Transfer/UploadCoordinator/Part.html +1048 -0
  380. data/doc/Files/Transfer/UploadCoordinator/Region.html +295 -0
  381. data/doc/Files/Transfer/UploadCoordinator/Segments.html +299 -0
  382. data/doc/Files/Transfer/UploadCoordinator/Source.html +725 -0
  383. data/doc/Files/Transfer/UploadCoordinator/StreamSource.html +664 -0
  384. data/doc/Files/Transfer/UploadCoordinator.html +546 -0
  385. data/doc/Files/Transfer/UploadPlan.html +522 -0
  386. data/doc/Files/Transfer/VersionChangedError.html +235 -0
  387. data/doc/Files/Transfer.html +134 -0
  388. data/doc/Files/TrialExpiredError.html +1 -1
  389. data/doc/Files/TrialLockedError.html +1 -1
  390. data/doc/Files/TwoFactorAuthenticationCodeAlreadySentError.html +1 -1
  391. data/doc/Files/TwoFactorAuthenticationCountryBlacklistedError.html +1 -1
  392. data/doc/Files/TwoFactorAuthenticationErrorError.html +1 -1
  393. data/doc/Files/TwoFactorAuthenticationGeneralErrorError.html +1 -1
  394. data/doc/Files/TwoFactorAuthenticationMethodUnsupportedErrorError.html +1 -1
  395. data/doc/Files/TwoFactorAuthenticationRequiredError.html +1 -1
  396. data/doc/Files/TwoFactorAuthenticationSetupExpiredError.html +1 -1
  397. data/doc/Files/TwoFactorAuthenticationUnsubscribedRecipientError.html +1 -1
  398. data/doc/Files/URI.html +1 -1
  399. data/doc/Files/UnrecognizedSortIndexError.html +1 -1
  400. data/doc/Files/UnsupportedCurrencyError.html +1 -1
  401. data/doc/Files/UnsupportedHttpResponseFormatError.html +1 -1
  402. data/doc/Files/UnsupportedMediaTypeError.html +1 -1
  403. data/doc/Files/UpdatesNotAllowedForRemotesError.html +1 -1
  404. data/doc/Files/UploadsUnavailableError.html +1 -1
  405. data/doc/Files/UsageByTopLevelDir.html +1 -1
  406. data/doc/Files/UsageDailySnapshot.html +1 -1
  407. data/doc/Files/UsageSnapshot.html +1 -1
  408. data/doc/Files/User.html +597 -386
  409. data/doc/Files/UserAdditionalEmailRecipient.html +1 -1
  410. data/doc/Files/UserCipherUse.html +1 -1
  411. data/doc/Files/UserIdInvalidError.html +1 -1
  412. data/doc/Files/UserIdOnUserEndpointError.html +1 -1
  413. data/doc/Files/UserIdWithoutSiteAdminError.html +1 -1
  414. data/doc/Files/UserLifecycleRule.html +1 -1
  415. data/doc/Files/UserNotFoundError.html +1 -1
  416. data/doc/Files/UserRequest.html +1 -1
  417. data/doc/Files/UserRequestsEnabledRequiredError.html +1 -1
  418. data/doc/Files/UserRequiredError.html +1 -1
  419. data/doc/Files/UserSecurityEvent.html +1 -1
  420. data/doc/Files/UserSftpClientUse.html +1 -1
  421. data/doc/Files/Util/LogSettings.html +1 -1
  422. data/doc/Files/Util.html +1 -1
  423. data/doc/Files/WebDavActionLog.html +1 -1
  424. data/doc/Files/WebhookTest.html +1 -1
  425. data/doc/Files/Workspace.html +1 -1
  426. data/doc/Files/WriteAndBundlePermissionRequiredError.html +1 -1
  427. data/doc/Files/WritePermissionRequiredError.html +1 -1
  428. data/doc/Files/ZipListEntry.html +1 -1
  429. data/doc/Files.html +116 -116
  430. data/doc/_index.html +314 -4
  431. data/doc/class_list.html +1 -1
  432. data/doc/file.README.html +1 -1
  433. data/doc/index.html +1 -1
  434. data/doc/method_list.html +5368 -3048
  435. data/doc/top-level-namespace.html +1 -1
  436. data/docs/file.md +346 -0
  437. data/docs/site.md +10 -0
  438. data/docs/user.md +8 -0
  439. data/lib/files.com/api.rb +6 -1
  440. data/lib/files.com/api_client.rb +220 -32
  441. data/lib/files.com/models/file.rb +124 -17
  442. data/lib/files.com/models/site.rb +16 -0
  443. data/lib/files.com/models/user.rb +19 -0
  444. data/lib/files.com/transfer/budgets.rb +123 -0
  445. data/lib/files.com/transfer/checkpoint.rb +113 -0
  446. data/lib/files.com/transfer/clock.rb +14 -0
  447. data/lib/files.com/transfer/controller.rb +549 -0
  448. data/lib/files.com/transfer/download_coordinator.rb +906 -0
  449. data/lib/files.com/transfer/errors.rb +100 -0
  450. data/lib/files.com/transfer/http_transport.rb +337 -0
  451. data/lib/files.com/transfer/job.rb +778 -0
  452. data/lib/files.com/transfer/options.rb +126 -0
  453. data/lib/files.com/transfer/policy.rb +91 -0
  454. data/lib/files.com/transfer/storage_retry.rb +169 -0
  455. data/lib/files.com/transfer/upload_coordinator.rb +657 -0
  456. data/lib/files.com/transfer/upload_plan.rb +157 -0
  457. data/lib/files.com.rb +13 -0
  458. data/spec/lib/api_client_spec.rb +125 -3
  459. data/spec/models/file_transfer_spec.rb +53 -4
  460. data/spec/support/transfer_server.rb +113 -14
  461. data/spec/transfer/adaptive_download_spec.rb +1102 -0
  462. data/spec/transfer/adaptive_upload_spec.rb +1602 -0
  463. data/spec/transfer/concurrency_controller_spec.rb +382 -0
  464. data/spec/workspace_id_spec.rb +19 -14
  465. metadata +59 -1
@@ -0,0 +1,382 @@
1
+ require "spec_helper"
2
+
3
+ # The real controller and policies, driven by a clock the examples move by hand. Every attempt starts and finishes at
4
+ # a time the example chooses; nothing in the controller is stubbed.
5
+ RSpec.describe Files::Transfer::Controller do
6
+ let(:mib) { 1024 * 1024 }
7
+ let(:clock) do
8
+ Class.new do
9
+ attr_reader :now
10
+
11
+ def initialize
12
+ @now = 0.0
13
+ end
14
+
15
+ def advance(seconds)
16
+ @now += seconds
17
+ end
18
+ end.new
19
+ end
20
+
21
+ def controller(policy)
22
+ described_class.new(policy, clock: clock)
23
+ end
24
+
25
+ def storage(startup = :default, **options)
26
+ Files::Transfer::Policy.storage_upload(startup: startup, **options)
27
+ end
28
+
29
+ # Starts count attempts at once, lets seconds pass and finishes each with bytes.
30
+ def round(controller, seconds:, bytes: mib, count: controller.limit)
31
+ attempts = Array.new(count) { controller.start_attempt }
32
+ clock.advance(seconds)
33
+ attempts.each { |attempt| controller.finish_attempt(attempt, :success, bytes: bytes) }
34
+ end
35
+
36
+ def reasons(controller)
37
+ controller.decisions.map { |decision| decision[:reason] }
38
+ end
39
+
40
+ describe "starting" do
41
+ it "starts an upload to cloud storage at one request by default and at 32 when aggressive" do
42
+ expect([ controller(storage(:default)).limit, controller(storage(:default)).phase ]).to eq([ 1, :warm ])
43
+ expect([ controller(storage(:aggressive)).limit, controller(storage(:aggressive)).phase ]).to eq([ 32, :ordinary ])
44
+ end
45
+
46
+ it "starts direct destinations at 4 and downloads at 32, without a warm start" do
47
+ direct = controller(Files::Transfer::Policy.direct_upload)
48
+ download = controller(Files::Transfer::Policy.download)
49
+
50
+ expect([ direct.limit, direct.phase, direct.policy.max ]).to eq([ 4, :ordinary, 16 ])
51
+ expect([ download.limit, download.phase, download.policy.max ]).to eq([ 32, :ordinary, 64 ])
52
+ end
53
+
54
+ it "lets the caller's max_concurrency cap every start and maximum" do
55
+ expect(controller(storage(:aggressive, max_concurrency: 8)).limit).to eq(8)
56
+ expect(controller(Files::Transfer::Policy.direct_upload(max_concurrency: 2)).limit).to eq(2)
57
+ expect(Files::Transfer::Policy.direct_upload(max_concurrency: 200).max).to eq(16)
58
+ expect(storage(max_concurrency: 200).max).to eq(200)
59
+ end
60
+ end
61
+
62
+ describe "the warm start" do
63
+ it "warms the connection with its first window, takes its second as the baseline and probes upward while each step pays off" do
64
+ warm = controller(storage)
65
+ round(warm, seconds: 0.25)
66
+ expect([ warm.limit, reasons(warm) ]).to eq([ 1, %i[start warm_connection] ])
67
+
68
+ 2.times { round(warm, seconds: 0.25) } # the baseline, one request at a time: 4 MiB/s
69
+ expect(warm.limit).to eq(2)
70
+
71
+ round(warm, seconds: 0.25) # the round that filled the raised limit ends
72
+ expect(warm.limit).to eq(2)
73
+ round(warm, seconds: 0.25) # two at once: 8 MiB/s, at least 4 * (1 + 0.5 * 1 / 1)
74
+ expect(warm.limit).to eq(3)
75
+ expect(reasons(warm)).to eq(%i[start warm_connection warm_probe warm_settling warm_settled warm_probe])
76
+ end
77
+
78
+ it "judges a probe once every attempt that filled its raised limit has ended, or once enough answers came without one" do
79
+ warm = controller(storage)
80
+ 3.times { round(warm, seconds: 0.25) }
81
+ first, slow = Array.new(2) { warm.start_attempt } # they fill the raised limit of two
82
+ clock.advance(0.25)
83
+ warm.finish_attempt(first, :success, bytes: mib)
84
+ # While the slow one is still out, one more attempt at a time keeps the two the limit allows on the network.
85
+ round(warm, seconds: 0.125, count: 1) # a later, quicker answer closes a window, but the slow one is still out
86
+ expect([ warm.limit, reasons(warm).last ]).to eq([ 2, :warm_settling ])
87
+
88
+ 13.times { round(warm, seconds: 0.125, count: 1) } # fifteen answers since the raise
89
+ expect([ warm.limit, warm.admitted ]).to eq([ 2, 1 ])
90
+ round(warm, seconds: 0.125, count: 1) # sixteen, at 8 MiB/s: the window then closing judges the probe
91
+ expect(warm.limit).to eq(3)
92
+ warm.finish_attempt(slow, :success, bytes: mib)
93
+ end
94
+
95
+ it "returns after a probe that does not pay off, rests two windows of ordinary size and probes again by one" do
96
+ warm = controller(storage)
97
+ 4.times { round(warm, seconds: 0.25) } # warmed, the baseline, raised to two and settled
98
+ round(warm, seconds: 0.5) # two at once, each twice as slow: no gain
99
+ expect(warm.limit).to eq(1)
100
+
101
+ 16.times { round(warm, seconds: 0.25) } # one rest window of sixteen answers
102
+ expect([ warm.limit, reasons(warm).last ]).to eq([ 1, :rest ])
103
+ 16.times { round(warm, seconds: 0.25) } # the last rest window is the next baseline
104
+ expect(warm.limit).to eq(2)
105
+ expect(reasons(warm)).to eq(%i[start warm_connection warm_probe warm_settling warm_settled warm_reject rest warm_probe])
106
+ end
107
+
108
+ it "keeps warming below its start after a second rejected probe" do
109
+ warm = controller(storage)
110
+ 4.times { round(warm, seconds: 0.25) }
111
+ round(warm, seconds: 0.5)
112
+ 32.times { round(warm, seconds: 0.25) }
113
+ round(warm, seconds: 0.25)
114
+ round(warm, seconds: 0.5) # no gain again
115
+
116
+ expect([ warm.limit, warm.phase ]).to eq([ 1, :warm ])
117
+ expect(reasons(warm).last(2)).to eq(%i[warm_settled warm_reject])
118
+ end
119
+
120
+ it "rests instead of probing when its baseline already queues" do
121
+ warm = controller(storage)
122
+ round(warm, seconds: 0.25)
123
+ 2.times { round(warm, seconds: 0.75) } # each answer three times slower than the warming one
124
+ expect([ warm.limit, reasons(warm).last ]).to eq([ 1, :warm_queued ])
125
+
126
+ 32.times { round(warm, seconds: 0.25) } # two rest windows of sixteen answers
127
+ expect(warm.limit).to eq(2)
128
+ expect(reasons(warm).last(3)).to eq(%i[warm_queued rest warm_probe])
129
+ end
130
+
131
+ it "abandons a probe after a failure in any epoch and rests where the failure left it, still warming" do
132
+ current = controller(storage)
133
+ 3.times { round(current, seconds: 0.25) }
134
+ failing, other = Array.new(2) { current.start_attempt } # sent at the raised limit
135
+ current.finish_attempt(failing, :failure)
136
+ current.finish_attempt(other, :success, bytes: mib)
137
+ expect([ current.limit, current.phase, reasons(current).last ]).to eq([ 1, :warm, :failure ])
138
+
139
+ stale = controller(storage)
140
+ round(stale, seconds: 0.25)
141
+ early = stale.start_attempt # sent at the baseline's limit, in its epoch
142
+ 2.times { round(stale, seconds: 0.25) }
143
+ expect(stale.limit).to eq(2)
144
+ stale.finish_attempt(early, :failure)
145
+ expect([ stale.limit, stale.phase, reasons(stale).last ]).to eq([ 2, :warm, :warm_interrupted ])
146
+ end
147
+
148
+ it "asks a probe for more answers when its baseline's rates varied" do
149
+ warm = controller(storage)
150
+ round(warm, seconds: 0.25)
151
+ round(warm, seconds: 0.25)
152
+ round(warm, seconds: 0.5)
153
+ expect(warm.limit).to eq(2)
154
+
155
+ round(warm, seconds: 0.25) # the raised round settles
156
+ 7.times { round(warm, seconds: 0.25) } # fourteen of the sixteen answers it needs
157
+ expect(warm.limit).to eq(2)
158
+ round(warm, seconds: 0.25)
159
+ expect(warm.limit).to eq(3)
160
+ end
161
+
162
+ it "goes straight to 32 from its first window on a link of at least 96 MiB/s" do
163
+ warm = controller(storage)
164
+ round(warm, seconds: 0.5, bytes: 64 * mib)
165
+
166
+ expect([ warm.limit, warm.phase ]).to eq([ 32, :ordinary ])
167
+ expect(reasons(warm)).to eq(%i[start fast_link])
168
+ end
169
+
170
+ it "keeps a probe whose larger parts take longer but less time per byte" do
171
+ warm = controller(storage)
172
+ 3.times { round(warm, seconds: 1.0, bytes: 4 * mib) } # one 4 MiB part a second
173
+ expect(warm.limit).to eq(2)
174
+
175
+ 2.times { round(warm, seconds: 2.0, bytes: 16 * mib) } # the raised round settles; then two 16 MiB parts, each two seconds
176
+ expect(warm.limit).to eq(3)
177
+ expect(reasons(warm)).to eq(%i[start warm_connection warm_probe warm_settling warm_settled warm_probe])
178
+ end
179
+
180
+ it "decides for parts of varying sizes as for equal parts at the same speed per byte" do
181
+ decide = lambda do |sizes|
182
+ warm = controller(storage)
183
+ sizes.each { |size| round(warm, seconds: size * 0.25, bytes: size * mib) }
184
+ [ warm.limit, reasons(warm) ]
185
+ end
186
+
187
+ expect(decide.call([ 1, 1, 4, 2, 3, 1, 2 ])).to eq(decide.call([ 1, 1, 1, 1, 1, 1, 1 ]))
188
+ expect(decide.call([ 1, 1, 1, 1, 1, 1, 1 ]))
189
+ .to eq([ 5, %i[start warm_connection warm_probe warm_settling warm_settled warm_probe warm_settling warm_settled warm_probe] ])
190
+ end
191
+
192
+ it "sizes a probe's window from the variation of every judged warm window, at its raised target" do
193
+ warm = controller(storage)
194
+ 3.times { round(warm, seconds: 0.25) }
195
+ round(warm, seconds: 0.25) # the raised round settles
196
+ expect(warm.limit).to eq(2)
197
+
198
+ first, second = Array.new(2) { warm.start_attempt }
199
+ clock.advance(0.2)
200
+ warm.finish_attempt(first, :success, bytes: mib)
201
+ clock.advance(0.006)
202
+ warm.finish_attempt(second, :success, bytes: mib)
203
+ expect(warm.limit).to eq(3)
204
+
205
+ # S = 2 * (0.003 / 0.203)^2 over f = 2 degrees bounds v; at its raised target 3, d = 1, the probe needs
206
+ # ceil(2 * v * (3 * 2 / 0.5)^2) = 6 answers, where the target it came from would have asked for 3.
207
+ round(warm, seconds: 0.2) # the raised round settles
208
+ round(warm, seconds: 0.2)
209
+ expect(warm.limit).to eq(3)
210
+ round(warm, seconds: 0.2)
211
+ expect(warm.limit).to eq(5)
212
+ end
213
+ end
214
+
215
+ describe "measurement" do
216
+ it "counts an attempt against the limit from its admission, but as network time only from its send to its answer" do
217
+ warm = controller(storage)
218
+ 2.times do
219
+ attempt = warm.admit
220
+ expect([ warm.admitted, warm.inflight ]).to eq([ 1, 0 ])
221
+ clock.advance(4.0) # waiting for a worker and reading the part
222
+ warm.sending(attempt)
223
+ expect(warm.inflight).to eq(1)
224
+ clock.advance(0.25)
225
+ warm.answered(attempt)
226
+ clock.advance(3.0) # settling the outcome and the caller's callbacks
227
+ warm.finish_attempt(attempt, :success, bytes: mib)
228
+ expect([ warm.admitted, warm.inflight ]).to eq([ 0, 0 ])
229
+ end
230
+
231
+ # Each warming window, of one answer, was on the network for 0.25 of 7.25 seconds: far too little to judge.
232
+ expect([ warm.limit, reasons(warm) ]).to eq([ 1, %i[start ineligible ineligible] ])
233
+ end
234
+ end
235
+
236
+ describe "after the warm start" do
237
+ it "keeps probes that gain 1%, by one at and above soft" do
238
+ steady = controller(storage(:aggressive))
239
+ 3.times { round(steady, seconds: 1.0) }
240
+
241
+ expect(steady.limit).to eq(35)
242
+ expect(reasons(steady)).to eq(%i[start probe probe_earned probe_earned])
243
+ end
244
+
245
+ it "grows by two below soft" do
246
+ steady = controller(storage(:aggressive))
247
+ steady.finish_attempt(steady.start_attempt, :failure)
248
+ round(steady, seconds: 1.0)
249
+
250
+ expect(steady.limit).to eq(22)
251
+ end
252
+
253
+ it "gives a probe up after two windows that do not gain, then holds a window" do
254
+ steady = controller(storage(:aggressive))
255
+ round(steady, seconds: 1.0) # 32 MiB/s
256
+ 2.times { round(steady, seconds: 33.0 / 32) } # still 32 MiB/s with 33 in flight
257
+ expect(steady.limit).to eq(32)
258
+
259
+ round(steady, seconds: 1.0)
260
+ expect(steady.limit).to eq(32)
261
+ round(steady, seconds: 1.0)
262
+ expect(steady.limit).to eq(33)
263
+ expect(reasons(steady)).to eq(%i[start probe probe_miss probe_rejected hold probe])
264
+ end
265
+
266
+ it "gives a probe up and stops growing while the queue estimate is at least 20" do
267
+ steady = controller(storage(:aggressive))
268
+ round(steady, seconds: 1.0)
269
+ round(steady, seconds: 3.0) # Q = 33 * (1 - 1 / 3)
270
+ round(steady, seconds: 3.0) # Q = 32 * (1 - 1 / 3)
271
+
272
+ expect(steady.limit).to eq(32)
273
+ expect(reasons(steady).last(2)).to eq(%i[probe_rejected queue_suppress])
274
+ end
275
+
276
+ it "shrinks by 8% when the queue estimate reaches 34" do
277
+ steady = controller(storage(:aggressive))
278
+ 6.times { round(steady, seconds: 1.0) }
279
+ expect(steady.limit).to eq(38)
280
+
281
+ round(steady, seconds: 20.0) # Q = 38 * (1 - 1 / 20)
282
+ expect(steady.limit).to eq(34)
283
+ expect(reasons(steady).last).to eq(:queue_backoff)
284
+ end
285
+
286
+ it "judges no window whose requests in flight averaged under 75% of the limit" do
287
+ steady = controller(storage(:aggressive))
288
+ 4.times { round(steady, seconds: 1.0, count: 8) }
289
+
290
+ expect(steady.limit).to eq(32)
291
+ expect(reasons(steady)).to eq(%i[start ineligible])
292
+ end
293
+ end
294
+
295
+ describe "failures and throttles" do
296
+ it "shrinks by 35% once an epoch, never below the minimum" do
297
+ shrinking = controller(storage(:aggressive))
298
+ first, second = Array.new(2) { shrinking.start_attempt }
299
+ shrinking.finish_attempt(first, :failure)
300
+ shrinking.finish_attempt(second, :failure) # started before the change
301
+ expect(shrinking.limit).to eq(20)
302
+
303
+ limits = Array.new(5) { shrinking.finish_attempt(shrinking.start_attempt, :failure) }
304
+ expect(limits).to eq([ 13, 8, 5, 4, 4 ])
305
+ end
306
+
307
+ it "shrinks by 10% for a throttle from the current epoch and measures nothing until its cooldown ends" do
308
+ throttled = controller(storage(:aggressive))
309
+ first, second = Array.new(2) { throttled.start_attempt }
310
+ throttled.finish_attempt(first, :throttle)
311
+ throttled.finish_attempt(second, :throttle)
312
+ expect(throttled.limit).to eq(28)
313
+ expect(reasons(throttled)).to eq(%i[start throttle throttle_cooldown])
314
+
315
+ round(throttled, seconds: 0.5) # completes within the cooldown
316
+ expect(reasons(throttled).last).to eq(:throttle_cooldown)
317
+
318
+ clock.advance(0.5)
319
+ round(throttled, seconds: 1.0)
320
+ expect(throttled.limit).to eq(30)
321
+ expect(reasons(throttled).last).to eq(:probe)
322
+ end
323
+
324
+ it "learns nothing from an ignored outcome, and a fixed policy nothing at all" do
325
+ steady = controller(storage(:aggressive))
326
+ steady.finish_attempt(steady.start_attempt, :ignored)
327
+ expect(reasons(steady)).to eq(%i[start])
328
+
329
+ fixed = controller(Files::Transfer::Policy.fixed(3))
330
+ fixed.finish_attempt(fixed.start_attempt, :failure)
331
+ fixed.finish_attempt(fixed.start_attempt, :throttle, retry_after: 5)
332
+ 5.times { round(fixed, seconds: 1.0) }
333
+ expect(fixed.limit).to eq(3)
334
+ expect(reasons(fixed)).to eq(%i[start])
335
+ end
336
+
337
+ it "counts a success sent before a failure's shrink in the window after it" do
338
+ steady = controller(storage(:aggressive))
339
+ early = steady.start_attempt
340
+ steady.finish_attempt(steady.start_attempt, :failure) # 32 to 20, in a new epoch
341
+ later = Array.new(19) { steady.start_attempt }
342
+ clock.advance(1.0)
343
+ ([ early ] + later).each { |attempt| steady.finish_attempt(attempt, :success, bytes: mib) }
344
+
345
+ # Twenty answers, the early one included, close the window at the new limit, which then grows.
346
+ expect(steady.limit).to eq(22)
347
+ expect(reasons(steady)).to eq(%i[start failure probe])
348
+ end
349
+
350
+ it "keeps the current epoch through a stale throttle, so a later attempt's failure still shrinks the limit once" do
351
+ steady = controller(storage(:aggressive))
352
+ first, stale = Array.new(2) { steady.start_attempt }
353
+ steady.finish_attempt(first, :throttle) # 32 to 28, in a new epoch
354
+ later = steady.start_attempt
355
+ steady.finish_attempt(stale, :throttle, retry_after: 2) # sent before that change: restarts measurement, shrinks nothing
356
+ expect(steady.limit).to eq(28)
357
+
358
+ steady.finish_attempt(later, :failure) # sent after it: 28 to 18
359
+ expect(steady.limit).to eq(18)
360
+ expect(reasons(steady)).to eq(%i[start throttle throttle_cooldown failure])
361
+ end
362
+
363
+ it "holds a destination back until a throttle's Retry-After, which a later one extends but never shortens, whichever request met it" do
364
+ holds = Files::Transfer::Holds.new(clock: clock)
365
+ destination = Files::Transfer::Holds.destination("https://storage.example.test/parts/1?X-Amz-Signature=fixture")
366
+ expect(Files::Transfer::Holds.destination("https://Storage.example.test:443/objects/2")).to eq(destination)
367
+
368
+ holds.hold(destination, 5)
369
+ expect(holds.deadline(destination)).to eq(5.0)
370
+ clock.advance(1.0)
371
+ holds.hold(destination, 2)
372
+ expect(holds.deadline(destination)).to eq(5.0)
373
+ holds.hold(destination, 8)
374
+ holds.hold(destination, 0) # a throttle without a Retry-After holds nothing back
375
+ expect(holds.deadline(destination)).to eq(9.0)
376
+ expect(holds.to_h).to eq({ "https://storage.example.test:443" => 8.0 })
377
+ expect(holds.deadline(Files::Transfer::Holds.destination("https://other.example.test/parts/1"))).to be_nil
378
+ clock.advance(8.0)
379
+ expect(holds.deadline(destination)).to be_nil
380
+ end
381
+ end
382
+ end
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require_relative "support/stubbed_api"
2
3
 
3
4
  RSpec.describe "Workspace scoping" do
4
5
  around do |example|
@@ -10,8 +11,24 @@ RSpec.describe "Workspace scoping" do
10
11
  end
11
12
 
12
13
  describe Files::ApiClient do
14
+ include StubbedApi
15
+
13
16
  let(:client) { described_class.new }
14
17
 
18
+ # The X-Files-Workspace-Id of each request to list folders sent through the SDK's own connection, as Faraday's
19
+ # adapter received it.
20
+ def sent_workspace_ids(**options)
21
+ sent = []
22
+ stubbed = stubbed_api_client do |stub|
23
+ stub.get("/api/rest/v1/folders") do |env|
24
+ sent << env.request_headers["X-Files-Workspace-Id"]
25
+ json_response(200, [])
26
+ end
27
+ end
28
+ stubbed.execute_request(:get, "/folders", api_key: "api-key", **options)
29
+ sent
30
+ end
31
+
15
32
  it "includes the configured workspace ID header" do
16
33
  headers = client.send(:request_headers, "api-key", nil, :get, 123)
17
34
 
@@ -26,26 +43,14 @@ RSpec.describe "Workspace scoping" do
26
43
 
27
44
  it "falls back to the configured workspace ID" do
28
45
  Files.workspace_id = 123
29
- response = double(status: 204, body: "", headers: {})
30
- conn = double
31
- client = described_class.new(conn)
32
46
 
33
- expect(client).to receive(:request_headers).with("api-key", nil, :get, 123).and_return({})
34
- expect(conn).to receive(:run_request).and_return(response)
35
-
36
- client.execute_request(:get, "/folders", api_key: "api-key")
47
+ expect(sent_workspace_ids).to eq([ "123" ])
37
48
  end
38
49
 
39
50
  it "lets a per-request workspace ID override the configured workspace ID" do
40
51
  Files.workspace_id = 123
41
- response = double(status: 204, body: "", headers: {})
42
- conn = double
43
- client = described_class.new(conn)
44
-
45
- expect(client).to receive(:request_headers).with("api-key", nil, :get, 456).and_return({})
46
- expect(conn).to receive(:run_request).and_return(response)
47
52
 
48
- client.execute_request(:get, "/folders", api_key: "api-key", workspace_id: 456)
53
+ expect(sent_workspace_ids(workspace_id: 456)).to eq([ "456" ])
49
54
  end
50
55
  end
51
56
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: files.com
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.813
4
+ version: 1.1.815
5
5
  platform: ruby
6
6
  authors:
7
7
  - files.com
@@ -196,6 +196,7 @@ files:
196
196
  - doc/Files/Api.html
197
197
  - doc/Files/ApiClient.html
198
198
  - doc/Files/ApiClient/RequestLogContext.html
199
+ - doc/Files/ApiClient/TransferSettings.html
199
200
  - doc/Files/ApiKey.html
200
201
  - doc/Files/ApiKeyIsDisabledError.html
201
202
  - doc/Files/ApiKeyIsPathRestrictedError.html
@@ -515,6 +516,47 @@ files:
515
516
  - doc/Files/TooManyLoginAttemptsError.html
516
517
  - doc/Files/TooManyRequestsError.html
517
518
  - doc/Files/TooManySharesError.html
519
+ - doc/Files/Transfer.html
520
+ - doc/Files/Transfer/BufferLimitError.html
521
+ - doc/Files/Transfer/ByteBudget.html
522
+ - doc/Files/Transfer/ByteBudget/Reservation.html
523
+ - doc/Files/Transfer/CancelledError.html
524
+ - doc/Files/Transfer/Checkpoint.html
525
+ - doc/Files/Transfer/CheckpointError.html
526
+ - doc/Files/Transfer/ClientTransport.html
527
+ - doc/Files/Transfer/ClientTransport/ClientResponse.html
528
+ - doc/Files/Transfer/ClientTransport/Reader.html
529
+ - doc/Files/Transfer/Clock.html
530
+ - doc/Files/Transfer/Control.html
531
+ - doc/Files/Transfer/Controller.html
532
+ - doc/Files/Transfer/Controller/Attempt.html
533
+ - doc/Files/Transfer/Coordinator.html
534
+ - doc/Files/Transfer/Coordinator/Timing.html
535
+ - doc/Files/Transfer/DownloadCoordinator.html
536
+ - doc/Files/Transfer/DownloadCoordinator/FileSink.html
537
+ - doc/Files/Transfer/DownloadCoordinator/IoSink.html
538
+ - doc/Files/Transfer/DownloadCoordinator/Piece.html
539
+ - doc/Files/Transfer/FileSlots.html
540
+ - doc/Files/Transfer/FrontendResponseError.html
541
+ - doc/Files/Transfer/Holds.html
542
+ - doc/Files/Transfer/HttpTransport.html
543
+ - doc/Files/Transfer/Job.html
544
+ - doc/Files/Transfer/Options.html
545
+ - doc/Files/Transfer/PausedError.html
546
+ - doc/Files/Transfer/Policy.html
547
+ - doc/Files/Transfer/RequestPermits.html
548
+ - doc/Files/Transfer/SourceChangedError.html
549
+ - doc/Files/Transfer/StorageResponse.html
550
+ - doc/Files/Transfer/StorageRetry.html
551
+ - doc/Files/Transfer/UploadCoordinator.html
552
+ - doc/Files/Transfer/UploadCoordinator/Grant.html
553
+ - doc/Files/Transfer/UploadCoordinator/Part.html
554
+ - doc/Files/Transfer/UploadCoordinator/Region.html
555
+ - doc/Files/Transfer/UploadCoordinator/Segments.html
556
+ - doc/Files/Transfer/UploadCoordinator/Source.html
557
+ - doc/Files/Transfer/UploadCoordinator/StreamSource.html
558
+ - doc/Files/Transfer/UploadPlan.html
559
+ - doc/Files/Transfer/VersionChangedError.html
518
560
  - doc/Files/TrialExpiredError.html
519
561
  - doc/Files/TrialLockedError.html
520
562
  - doc/Files/TwoFactorAuthenticationCodeAlreadySentError.html
@@ -874,6 +916,19 @@ files:
874
916
  - lib/files.com/response.rb
875
917
  - lib/files.com/sizable_io.rb
876
918
  - lib/files.com/system_profiler.rb
919
+ - lib/files.com/transfer/budgets.rb
920
+ - lib/files.com/transfer/checkpoint.rb
921
+ - lib/files.com/transfer/clock.rb
922
+ - lib/files.com/transfer/controller.rb
923
+ - lib/files.com/transfer/download_coordinator.rb
924
+ - lib/files.com/transfer/errors.rb
925
+ - lib/files.com/transfer/http_transport.rb
926
+ - lib/files.com/transfer/job.rb
927
+ - lib/files.com/transfer/options.rb
928
+ - lib/files.com/transfer/policy.rb
929
+ - lib/files.com/transfer/storage_retry.rb
930
+ - lib/files.com/transfer/upload_coordinator.rb
931
+ - lib/files.com/transfer/upload_plan.rb
877
932
  - lib/files.com/uri.rb
878
933
  - lib/files.com/util.rb
879
934
  - lib/files.com/version.rb
@@ -905,6 +960,9 @@ files:
905
960
  - spec/spec_helper.rb
906
961
  - spec/support/stubbed_api.rb
907
962
  - spec/support/transfer_server.rb
963
+ - spec/transfer/adaptive_download_spec.rb
964
+ - spec/transfer/adaptive_upload_spec.rb
965
+ - spec/transfer/concurrency_controller_spec.rb
908
966
  - spec/uri_spec.rb
909
967
  - spec/workspace_id_spec.rb
910
968
  - test.sh