files.com 1.1.813 → 1.1.814
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.
- checksums.yaml +4 -4
- data/_VERSION +1 -1
- data/doc/Files/APIConnectionError.html +1 -1
- data/doc/Files/APIError.html +1 -1
- data/doc/Files/AccountAlreadyExistsError.html +1 -1
- data/doc/Files/AccountLineItem.html +1 -1
- data/doc/Files/AccountOverdueError.html +1 -1
- data/doc/Files/Action.html +1 -1
- data/doc/Files/ActionLog.html +1 -1
- data/doc/Files/ActionNotificationExport.html +1 -1
- data/doc/Files/ActionNotificationExportResult.html +1 -1
- data/doc/Files/AdditionalAuthenticationRequiredError.html +1 -1
- data/doc/Files/AgentNode.html +1 -1
- data/doc/Files/AgentNodeConnection.html +1 -1
- data/doc/Files/AgentNodeInstance.html +1 -1
- data/doc/Files/AgentPushUpdate.html +1 -1
- data/doc/Files/AgentPushUpdateBlockedError.html +1 -1
- data/doc/Files/AgentUnavailableError.html +1 -1
- data/doc/Files/AgentUpgradeRequiredError.html +1 -1
- data/doc/Files/AiAssistantPersonality.html +1 -1
- data/doc/Files/AiTask.html +1 -1
- data/doc/Files/AiTaskCannotBeRunManuallyError.html +1 -1
- data/doc/Files/AlreadyCompletedError.html +1 -1
- data/doc/Files/Api.html +20 -13
- data/doc/Files/ApiClient/RequestLogContext.html +29 -29
- data/doc/Files/ApiClient/TransferSettings.html +721 -0
- data/doc/Files/ApiClient.html +756 -204
- data/doc/Files/ApiKey.html +1 -1
- data/doc/Files/ApiKeyIsDisabledError.html +1 -1
- data/doc/Files/ApiKeyIsPathRestrictedError.html +1 -1
- data/doc/Files/ApiKeyNotFoundError.html +1 -1
- data/doc/Files/ApiKeyOnlyForDesktopAppError.html +1 -1
- data/doc/Files/ApiKeyOnlyForFileOperationsError.html +1 -1
- data/doc/Files/ApiKeyOnlyForMobileAppError.html +1 -1
- data/doc/Files/ApiKeyOnlyForOfficeIntegrationError.html +1 -1
- data/doc/Files/ApiKeySessionsNotSupportedError.html +1 -1
- data/doc/Files/ApiRequestLog.html +1 -1
- data/doc/Files/App.html +1 -1
- data/doc/Files/As2IncomingMessage.html +1 -1
- data/doc/Files/As2OutgoingMessage.html +1 -1
- data/doc/Files/As2Partner.html +1 -1
- data/doc/Files/As2Station.html +1 -1
- data/doc/Files/AttachmentTooLargeError.html +1 -1
- data/doc/Files/AuthenticationError.html +1 -1
- data/doc/Files/AuthenticationRequiredError.html +1 -1
- data/doc/Files/Auto.html +1 -1
- data/doc/Files/Automation.html +1 -1
- data/doc/Files/AutomationAuthoringSchema.html +1 -1
- data/doc/Files/AutomationCannotBeRunManuallyError.html +1 -1
- data/doc/Files/AutomationExecutionNode.html +1 -1
- data/doc/Files/AutomationLog.html +1 -1
- data/doc/Files/AutomationRun.html +1 -1
- data/doc/Files/AutomationsUnavailableError.html +1 -1
- data/doc/Files/BadRequestError.html +1 -1
- data/doc/Files/BandwidthSnapshot.html +1 -1
- data/doc/Files/Behavior.html +1 -1
- data/doc/Files/BehaviorNotAllowedOnRemoteServerError.html +1 -1
- data/doc/Files/BillingInformationHiddenError.html +1 -1
- data/doc/Files/BillingPermissionRequiredError.html +1 -1
- data/doc/Files/BufferedUploadDisabledForThisDestinationError.html +1 -1
- data/doc/Files/Bundle.html +1 -1
- data/doc/Files/BundleAction.html +1 -1
- data/doc/Files/BundleDownload.html +1 -1
- data/doc/Files/BundleMaximumUsesReachedError.html +1 -1
- data/doc/Files/BundleNotification.html +1 -1
- data/doc/Files/BundleOnlyAllowsPreviewsError.html +1 -1
- data/doc/Files/BundleOperationRequiresSubfolderError.html +1 -1
- data/doc/Files/BundlePath.html +1 -1
- data/doc/Files/BundlePathNotFoundError.html +1 -1
- data/doc/Files/BundlePermissionRequiredError.html +1 -1
- data/doc/Files/BundleRecipient.html +1 -1
- data/doc/Files/BundleRegistration.html +1 -1
- data/doc/Files/BundleRegistrationCodeFailedError.html +1 -1
- data/doc/Files/BundleRegistrationNotFoundError.html +1 -1
- data/doc/Files/CannotAdministerHigherLevelUserError.html +1 -1
- data/doc/Files/CannotDownloadDirectoryError.html +1 -1
- data/doc/Files/CannotLoginWhileUsingKeyError.html +1 -1
- data/doc/Files/CantActForOtherUserError.html +1 -1
- data/doc/Files/CantMoveWithMultipleLocationsError.html +1 -1
- data/doc/Files/ChatMessage.html +1 -1
- data/doc/Files/ChatSession.html +1 -1
- data/doc/Files/ChildSiteManagementPolicy.html +1 -1
- data/doc/Files/Clickwrap.html +1 -1
- data/doc/Files/CodeNotFoundError.html +1 -1
- data/doc/Files/ConfigurationLockedPathError.html +1 -1
- data/doc/Files/ContactAdminForPasswordChangeHelpError.html +1 -1
- data/doc/Files/CouldNotCreateParentError.html +1 -1
- data/doc/Files/CustomDomain.html +1 -1
- data/doc/Files/DatetimeParseError.html +1 -1
- data/doc/Files/DesktopConfigurationProfile.html +1 -1
- data/doc/Files/DestinationExistsError.html +1 -1
- data/doc/Files/DestinationFolderLimitedError.html +1 -1
- data/doc/Files/DestinationParentConflictError.html +1 -1
- data/doc/Files/DestinationParentDoesNotExistError.html +1 -1
- data/doc/Files/DestinationSameError.html +1 -1
- data/doc/Files/DestinationSiteMismatchError.html +1 -1
- data/doc/Files/DirectConnectionInfo.html +1 -1
- data/doc/Files/DnsRecord.html +1 -1
- data/doc/Files/DoesNotSupportSortingError.html +1 -1
- data/doc/Files/DuplicateShareRecipientError.html +1 -1
- data/doc/Files/EmailIncomingMessage.html +1 -1
- data/doc/Files/EmailLog.html +1 -1
- data/doc/Files/Error.html +2 -2
- data/doc/Files/Errors.html +1 -1
- data/doc/Files/EventChannel.html +1 -1
- data/doc/Files/EventDeliveryAttempt.html +1 -1
- data/doc/Files/EventRecord.html +1 -1
- data/doc/Files/EventSubscription.html +1 -1
- data/doc/Files/EventTarget.html +1 -1
- data/doc/Files/ExavaultApiRequestLog.html +1 -1
- data/doc/Files/ExceededRuntimeLimitError.html +1 -1
- data/doc/Files/Expectation.html +1 -1
- data/doc/Files/ExpectationAlreadyHasOpenWindowError.html +1 -1
- data/doc/Files/ExpectationEvaluation.html +1 -1
- data/doc/Files/ExpectationIncident.html +1 -1
- data/doc/Files/ExpectationNotManualTriggerError.html +1 -1
- data/doc/Files/ExpiredPrivateKeyError.html +1 -1
- data/doc/Files/ExpiredPublicKeyError.html +1 -1
- data/doc/Files/ExportFailureError.html +1 -1
- data/doc/Files/ExportNotReadyError.html +1 -1
- data/doc/Files/ExternalEvent.html +1 -1
- data/doc/Files/FailedToChangePasswordError.html +1 -1
- data/doc/Files/File.html +2019 -1515
- data/doc/Files/FileAction.html +1 -1
- data/doc/Files/FileActionError.html +1 -1
- data/doc/Files/FileComment.html +1 -1
- data/doc/Files/FileCommentReaction.html +1 -1
- data/doc/Files/FileLockedError.html +1 -1
- data/doc/Files/FileMigration.html +1 -1
- data/doc/Files/FileMigrationLog.html +1 -1
- data/doc/Files/FileNotFoundError.html +1 -1
- data/doc/Files/FileNotUploadedError.html +1 -1
- data/doc/Files/FilePendingProcessingError.html +1 -1
- data/doc/Files/FileProcessingErrorError.html +1 -1
- data/doc/Files/FileTooBigToDecryptError.html +1 -1
- data/doc/Files/FileTooBigToEncryptError.html +1 -1
- data/doc/Files/FileUploadNotFoundError.html +1 -1
- data/doc/Files/FileUploadPart.html +1 -1
- data/doc/Files/FileUploadedToWrongRegionError.html +1 -1
- data/doc/Files/FileUtils.html +1 -1
- data/doc/Files/FilenameTooLongError.html +1 -1
- data/doc/Files/FilesAgentFailedAuthorizationError.html +1 -1
- data/doc/Files/FilesNativeStorageOverloadedError.html +1 -1
- data/doc/Files/Folder.html +1 -1
- data/doc/Files/FolderAdminOrBillingPermissionRequiredError.html +1 -1
- data/doc/Files/FolderAdminPermissionRequiredError.html +1 -1
- data/doc/Files/FolderLockedError.html +1 -1
- data/doc/Files/FolderMustNotBeAFileError.html +1 -1
- data/doc/Files/FolderNotEmptyError.html +1 -1
- data/doc/Files/FoldersNotAllowedError.html +1 -1
- data/doc/Files/FormField.html +1 -1
- data/doc/Files/FormFieldSet.html +1 -1
- data/doc/Files/FtpActionLog.html +1 -1
- data/doc/Files/FullPermissionRequiredError.html +1 -1
- data/doc/Files/GpgKey.html +1 -1
- data/doc/Files/Group.html +1 -1
- data/doc/Files/GroupNotFoundError.html +1 -1
- data/doc/Files/GroupUser.html +1 -1
- data/doc/Files/History.html +1 -1
- data/doc/Files/HistoryExport.html +1 -1
- data/doc/Files/HistoryExportResult.html +1 -1
- data/doc/Files/HistoryPermissionRequiredError.html +1 -1
- data/doc/Files/HistoryUnavailableError.html +1 -1
- data/doc/Files/HolidayCalendar.html +1 -1
- data/doc/Files/HolidayRegion.html +1 -1
- data/doc/Files/Image.html +1 -1
- data/doc/Files/InAppAiAssistantUnavailableError.html +1 -1
- data/doc/Files/InboundS3Log.html +1 -1
- data/doc/Files/InboxNotFoundError.html +1 -1
- data/doc/Files/InboxRecipient.html +1 -1
- data/doc/Files/InboxRegistration.html +1 -1
- data/doc/Files/InboxRegistrationCodeFailedError.html +1 -1
- data/doc/Files/InboxUpload.html +1 -1
- data/doc/Files/InsufficientPermissionForParamsError.html +1 -1
- data/doc/Files/InsufficientPermissionForSiteError.html +1 -1
- data/doc/Files/IntegrationCentricProfile.html +1 -1
- data/doc/Files/InternalGeneralErrorError.html +1 -1
- data/doc/Files/InvalidBodyError.html +1 -1
- data/doc/Files/InvalidBundleCodeError.html +1 -1
- data/doc/Files/InvalidCredentialsError.html +1 -1
- data/doc/Files/InvalidCursorError.html +1 -1
- data/doc/Files/InvalidCursorTypeForSortError.html +1 -1
- data/doc/Files/InvalidEtagsError.html +1 -1
- data/doc/Files/InvalidFileTypeError.html +1 -1
- data/doc/Files/InvalidFilenameError.html +1 -1
- data/doc/Files/InvalidFilterAliasCombinationError.html +1 -1
- data/doc/Files/InvalidFilterFieldError.html +1 -1
- data/doc/Files/InvalidFilterParamError.html +1 -1
- data/doc/Files/InvalidFilterParamFormatError.html +1 -1
- data/doc/Files/InvalidFilterParamValueError.html +1 -1
- data/doc/Files/InvalidInputEncodingError.html +1 -1
- data/doc/Files/InvalidInterfaceError.html +1 -1
- data/doc/Files/InvalidOauthError.html +1 -1
- data/doc/Files/InvalidOauthProviderError.html +1 -1
- data/doc/Files/InvalidOrExpiredCodeError.html +1 -1
- data/doc/Files/InvalidParameterError.html +5 -1
- data/doc/Files/InvalidPathError.html +1 -1
- data/doc/Files/InvalidPriorityColorError.html +1 -1
- data/doc/Files/InvalidRangeError.html +1 -1
- data/doc/Files/InvalidReturnToUrlError.html +1 -1
- data/doc/Files/InvalidSearchQueryError.html +1 -1
- data/doc/Files/InvalidSessionError.html +1 -1
- data/doc/Files/InvalidSiteError.html +1 -1
- data/doc/Files/InvalidSortFieldError.html +1 -1
- data/doc/Files/InvalidSortFilterCombinationError.html +1 -1
- data/doc/Files/InvalidUploadOffsetError.html +1 -1
- data/doc/Files/InvalidUploadPartGapError.html +1 -1
- data/doc/Files/InvalidUploadPartSizeError.html +1 -1
- data/doc/Files/InvalidUsernameOrPasswordError.html +1 -1
- data/doc/Files/InvalidWorkspaceIdHeaderError.html +1 -1
- data/doc/Files/InvalidZipFileError.html +1 -1
- data/doc/Files/Invoice.html +1 -1
- data/doc/Files/InvoiceLineItem.html +1 -1
- data/doc/Files/IpAddress.html +1 -1
- data/doc/Files/KeyLifecycleRule.html +1 -1
- data/doc/Files/List.html +1 -1
- data/doc/Files/Lock.html +1 -1
- data/doc/Files/LockOperationBusyError.html +1 -1
- data/doc/Files/LockedOutError.html +1 -1
- data/doc/Files/LockoutRegionMismatchError.html +1 -1
- data/doc/Files/MetadataCategory.html +1 -1
- data/doc/Files/MetadataNotSupportedOnRemotesError.html +1 -1
- data/doc/Files/MethodNotAllowedError.html +1 -1
- data/doc/Files/MigrationInProgressError.html +1 -1
- data/doc/Files/MissingParameterError.html +1 -1
- data/doc/Files/ModelSaveErrorError.html +1 -1
- data/doc/Files/MoverAccessDeniedError.html +1 -1
- data/doc/Files/MoverPackageRequiredError.html +1 -1
- data/doc/Files/MultipleProcessingErrorsError.html +1 -1
- data/doc/Files/MultipleSortParamsNotAllowedError.html +1 -1
- data/doc/Files/MustAuthenticateWithApiKeyError.html +1 -1
- data/doc/Files/NeedAdminPermissionForInboxError.html +1 -1
- data/doc/Files/NestedNotFoundError.html +1 -1
- data/doc/Files/NoAccountForSiteError.html +1 -1
- data/doc/Files/NoValidInputParamsError.html +1 -1
- data/doc/Files/NonAdminsMustQueryByFolderOrPathError.html +1 -1
- data/doc/Files/NotAllowedToCreateBundleError.html +1 -1
- data/doc/Files/NotAuthenticatedError.html +1 -1
- data/doc/Files/NotAuthorizedError.html +1 -1
- data/doc/Files/NotEnqueuableSyncError.html +1 -1
- data/doc/Files/NotFoundError.html +1 -1
- data/doc/Files/NotImplementedError.html +1 -1
- data/doc/Files/Notification.html +1 -1
- data/doc/Files/OffsetUploadNotAllowedWithMalwareScanningError.html +1 -1
- data/doc/Files/OneTimePasswordIncorrectError.html +1 -1
- data/doc/Files/OutboundConnectionLog.html +1 -1
- data/doc/Files/PartNumberTooLargeError.html +1 -1
- data/doc/Files/Partner.html +1 -1
- data/doc/Files/PartnerChannel.html +1 -1
- data/doc/Files/PartnerChannelTemplate.html +1 -1
- data/doc/Files/PartnerConnection.html +1 -1
- data/doc/Files/PartnerSite.html +1 -1
- data/doc/Files/PartnerSiteRequest.html +1 -1
- data/doc/Files/PasswordChangeNotRequiredError.html +1 -1
- data/doc/Files/PasswordChangeRequiredError.html +1 -1
- data/doc/Files/PathCannotHaveTrailingWhitespaceError.html +1 -1
- data/doc/Files/PathTooLongError.html +1 -1
- data/doc/Files/PathUtil.html +1 -1
- data/doc/Files/Payment.html +1 -1
- data/doc/Files/PaymentLineItem.html +1 -1
- data/doc/Files/PaymentMethodErrorError.html +1 -1
- data/doc/Files/PendingWorkEvent.html +1 -1
- data/doc/Files/Permission.html +1 -1
- data/doc/Files/PlanNotFoundError.html +1 -1
- data/doc/Files/Preview.html +1 -1
- data/doc/Files/PreviewOnlyPermissionCannotDownloadError.html +1 -1
- data/doc/Files/ProcessingFailureError.html +1 -1
- data/doc/Files/PublicHostingRequestLog.html +1 -1
- data/doc/Files/PublicIpAddress.html +1 -1
- data/doc/Files/PublicKey.html +1 -1
- data/doc/Files/RateLimitedError.html +1 -1
- data/doc/Files/ReadOnlySessionError.html +1 -1
- data/doc/Files/ReadPermissionRequiredError.html +1 -1
- data/doc/Files/ReauthenticationFailedError.html +1 -1
- data/doc/Files/ReauthenticationFailedFinalError.html +1 -1
- data/doc/Files/ReauthenticationNeededActionError.html +1 -1
- data/doc/Files/ReauthenticationNeededFieldsError.html +1 -1
- data/doc/Files/ReauthenticationRateLimitedError.html +1 -1
- data/doc/Files/RecaptchaFailedError.html +1 -1
- data/doc/Files/RecipientAlreadySharedError.html +1 -1
- data/doc/Files/RemoteBandwidthSnapshot.html +1 -1
- data/doc/Files/RemoteDesktopDebugLoggingDisabledError.html +1 -1
- data/doc/Files/RemoteEntryReadOnlyError.html +1 -1
- data/doc/Files/RemoteMountBackend.html +1 -1
- data/doc/Files/RemoteServer.html +1 -1
- data/doc/Files/RemoteServerConfigurationFile.html +1 -1
- data/doc/Files/RemoteServerCredential.html +1 -1
- data/doc/Files/RemoteServerErrorError.html +1 -1
- data/doc/Files/Request.html +1 -1
- data/doc/Files/RequestBodyTooLargeError.html +1 -1
- data/doc/Files/RequestParamsContainInvalidCharacterError.html +1 -1
- data/doc/Files/RequestParamsInvalidError.html +1 -1
- data/doc/Files/RequestParamsRequiredError.html +1 -1
- data/doc/Files/ResourceBelongsToParentSiteError.html +1 -1
- data/doc/Files/ResourceLockedError.html +1 -1
- data/doc/Files/Response.html +1 -1
- data/doc/Files/Restore.html +1 -1
- data/doc/Files/RootFolderBehaviorSiteAdminRequiredError.html +1 -1
- data/doc/Files/RootFolderBehaviorSkipSiteAdminRequiredError.html +1 -1
- data/doc/Files/Schedule.html +1 -1
- data/doc/Files/ScheduledExport.html +1 -1
- data/doc/Files/ScimLog.html +1 -1
- data/doc/Files/SearchAllOnChildPathError.html +1 -1
- data/doc/Files/SearchUnavailableError.html +1 -1
- data/doc/Files/Secret.html +1 -1
- data/doc/Files/SelfManagedRequiredError.html +1 -1
- data/doc/Files/ServiceUnavailableError.html +1 -1
- data/doc/Files/Session.html +1 -1
- data/doc/Files/SettingsChange.html +1 -1
- data/doc/Files/SftpActionLog.html +1 -1
- data/doc/Files/SftpHostKey.html +1 -1
- data/doc/Files/ShareGroup.html +1 -1
- data/doc/Files/ShareGroupMember.html +1 -1
- data/doc/Files/SiemHttpDestination.html +1 -1
- data/doc/Files/SiemHttpDestinationEvent.html +1 -1
- data/doc/Files/Site.html +1 -1
- data/doc/Files/SiteAdminOrPartnerAdminPermissionRequiredError.html +1 -1
- data/doc/Files/SiteAdminOrWorkspaceAdminOrFolderAdminPermissionRequiredError.html +1 -1
- data/doc/Files/SiteAdminOrWorkspaceAdminOrPartnerAdminOrFolderAdminPermissionRequiredError.html +1 -1
- data/doc/Files/SiteAdminOrWorkspaceAdminOrPartnerAdminPermissionRequiredError.html +1 -1
- data/doc/Files/SiteAdminOrWorkspaceAdminPermissionRequiredError.html +1 -1
- data/doc/Files/SiteAdminRequiredError.html +1 -1
- data/doc/Files/SiteConfigurationError.html +1 -1
- data/doc/Files/SiteDisabledError.html +1 -1
- data/doc/Files/SiteFilesAreImmutableError.html +1 -1
- data/doc/Files/SiteNotFoundError.html +1 -1
- data/doc/Files/SiteSubdomainRedirect.html +1 -1
- data/doc/Files/SiteWasRemovedError.html +1 -1
- data/doc/Files/SizableIO.html +1 -1
- data/doc/Files/Snapshot.html +1 -1
- data/doc/Files/SsoEvent.html +1 -1
- data/doc/Files/SsoStrategy.html +1 -1
- data/doc/Files/Status.html +1 -1
- data/doc/Files/Style.html +1 -1
- data/doc/Files/SubfolderLockedError.html +1 -1
- data/doc/Files/Sync.html +1 -1
- data/doc/Files/SyncInProgressError.html +1 -1
- data/doc/Files/SyncLog.html +1 -1
- data/doc/Files/SyncRun.html +1 -1
- data/doc/Files/SyncRunLiveTransfer.html +1 -1
- data/doc/Files/SystemProfiler.html +1 -1
- data/doc/Files/TooManyConcurrentLoginsError.html +1 -1
- data/doc/Files/TooManyConcurrentRequestsError.html +1 -1
- data/doc/Files/TooManyLoginAttemptsError.html +1 -1
- data/doc/Files/TooManyRequestsError.html +1 -1
- data/doc/Files/TooManySharesError.html +1 -1
- data/doc/Files/Transfer/BufferLimitError.html +175 -0
- data/doc/Files/Transfer/ByteBudget/Reservation.html +301 -0
- data/doc/Files/Transfer/ByteBudget.html +748 -0
- data/doc/Files/Transfer/CancelledError.html +235 -0
- data/doc/Files/Transfer/Checkpoint.html +1371 -0
- data/doc/Files/Transfer/CheckpointError.html +173 -0
- data/doc/Files/Transfer/ClientTransport/ClientResponse.html +661 -0
- data/doc/Files/Transfer/ClientTransport/Reader.html +530 -0
- data/doc/Files/Transfer/ClientTransport.html +675 -0
- data/doc/Files/Transfer/Clock.html +189 -0
- data/doc/Files/Transfer/Control.html +667 -0
- data/doc/Files/Transfer/Controller/Attempt.html +465 -0
- data/doc/Files/Transfer/Controller.html +1166 -0
- data/doc/Files/Transfer/Coordinator/Timing.html +568 -0
- data/doc/Files/Transfer/Coordinator.html +534 -0
- data/doc/Files/Transfer/DownloadCoordinator/FileSink.html +976 -0
- data/doc/Files/Transfer/DownloadCoordinator/IoSink.html +1168 -0
- data/doc/Files/Transfer/DownloadCoordinator/Piece.html +875 -0
- data/doc/Files/Transfer/DownloadCoordinator.html +728 -0
- data/doc/Files/Transfer/FileSlots.html +480 -0
- data/doc/Files/Transfer/FrontendResponseError.html +235 -0
- data/doc/Files/Transfer/Holds.html +505 -0
- data/doc/Files/Transfer/HttpTransport.html +579 -0
- data/doc/Files/Transfer/Job.html +2338 -0
- data/doc/Files/Transfer/Options.html +924 -0
- data/doc/Files/Transfer/PausedError.html +319 -0
- data/doc/Files/Transfer/Policy.html +1642 -0
- data/doc/Files/Transfer/RequestPermits.html +160 -0
- data/doc/Files/Transfer/SourceChangedError.html +235 -0
- data/doc/Files/Transfer/StorageResponse.html +546 -0
- data/doc/Files/Transfer/StorageRetry.html +1098 -0
- data/doc/Files/Transfer/UploadCoordinator/Grant.html +1048 -0
- data/doc/Files/Transfer/UploadCoordinator/Part.html +1048 -0
- data/doc/Files/Transfer/UploadCoordinator/Region.html +295 -0
- data/doc/Files/Transfer/UploadCoordinator/Segments.html +299 -0
- data/doc/Files/Transfer/UploadCoordinator/Source.html +725 -0
- data/doc/Files/Transfer/UploadCoordinator/StreamSource.html +664 -0
- data/doc/Files/Transfer/UploadCoordinator.html +546 -0
- data/doc/Files/Transfer/UploadPlan.html +522 -0
- data/doc/Files/Transfer/VersionChangedError.html +235 -0
- data/doc/Files/Transfer.html +134 -0
- data/doc/Files/TrialExpiredError.html +1 -1
- data/doc/Files/TrialLockedError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationCodeAlreadySentError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationCountryBlacklistedError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationErrorError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationGeneralErrorError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationMethodUnsupportedErrorError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationRequiredError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationSetupExpiredError.html +1 -1
- data/doc/Files/TwoFactorAuthenticationUnsubscribedRecipientError.html +1 -1
- data/doc/Files/URI.html +1 -1
- data/doc/Files/UnrecognizedSortIndexError.html +1 -1
- data/doc/Files/UnsupportedCurrencyError.html +1 -1
- data/doc/Files/UnsupportedHttpResponseFormatError.html +1 -1
- data/doc/Files/UnsupportedMediaTypeError.html +1 -1
- data/doc/Files/UpdatesNotAllowedForRemotesError.html +1 -1
- data/doc/Files/UploadsUnavailableError.html +1 -1
- data/doc/Files/UsageByTopLevelDir.html +1 -1
- data/doc/Files/UsageDailySnapshot.html +1 -1
- data/doc/Files/UsageSnapshot.html +1 -1
- data/doc/Files/User.html +1 -1
- data/doc/Files/UserAdditionalEmailRecipient.html +1 -1
- data/doc/Files/UserCipherUse.html +1 -1
- data/doc/Files/UserIdInvalidError.html +1 -1
- data/doc/Files/UserIdOnUserEndpointError.html +1 -1
- data/doc/Files/UserIdWithoutSiteAdminError.html +1 -1
- data/doc/Files/UserLifecycleRule.html +1 -1
- data/doc/Files/UserNotFoundError.html +1 -1
- data/doc/Files/UserRequest.html +1 -1
- data/doc/Files/UserRequestsEnabledRequiredError.html +1 -1
- data/doc/Files/UserRequiredError.html +1 -1
- data/doc/Files/UserSecurityEvent.html +1 -1
- data/doc/Files/UserSftpClientUse.html +1 -1
- data/doc/Files/Util/LogSettings.html +1 -1
- data/doc/Files/Util.html +1 -1
- data/doc/Files/WebDavActionLog.html +1 -1
- data/doc/Files/WebhookTest.html +1 -1
- data/doc/Files/Workspace.html +1 -1
- data/doc/Files/WriteAndBundlePermissionRequiredError.html +1 -1
- data/doc/Files/WritePermissionRequiredError.html +1 -1
- data/doc/Files/ZipListEntry.html +1 -1
- data/doc/Files.html +116 -116
- data/doc/_index.html +314 -4
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +1 -1
- data/doc/index.html +1 -1
- data/doc/method_list.html +4703 -2415
- data/doc/top-level-namespace.html +1 -1
- data/docs/file.md +346 -0
- data/lib/files.com/api.rb +6 -1
- data/lib/files.com/api_client.rb +220 -32
- data/lib/files.com/models/file.rb +124 -17
- data/lib/files.com/transfer/budgets.rb +123 -0
- data/lib/files.com/transfer/checkpoint.rb +113 -0
- data/lib/files.com/transfer/clock.rb +14 -0
- data/lib/files.com/transfer/controller.rb +549 -0
- data/lib/files.com/transfer/download_coordinator.rb +906 -0
- data/lib/files.com/transfer/errors.rb +100 -0
- data/lib/files.com/transfer/http_transport.rb +337 -0
- data/lib/files.com/transfer/job.rb +778 -0
- data/lib/files.com/transfer/options.rb +126 -0
- data/lib/files.com/transfer/policy.rb +91 -0
- data/lib/files.com/transfer/storage_retry.rb +169 -0
- data/lib/files.com/transfer/upload_coordinator.rb +657 -0
- data/lib/files.com/transfer/upload_plan.rb +157 -0
- data/lib/files.com.rb +13 -0
- data/spec/lib/api_client_spec.rb +125 -3
- data/spec/models/file_transfer_spec.rb +53 -4
- data/spec/support/transfer_server.rb +113 -14
- data/spec/transfer/adaptive_download_spec.rb +1102 -0
- data/spec/transfer/adaptive_upload_spec.rb +1602 -0
- data/spec/transfer/concurrency_controller_spec.rb +382 -0
- data/spec/workspace_id_spec.rb +19 -14
- metadata +59 -1
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
</div>
|
|
103
103
|
|
|
104
104
|
<div id="footer">
|
|
105
|
-
Generated on Tue Nov 3
|
|
105
|
+
Generated on Tue Nov 3 18:03:55 2026 by
|
|
106
106
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
107
107
|
0.9.45 (ruby-4.0.9).
|
|
108
108
|
</div>
|
data/docs/file.md
CHANGED
|
@@ -40,6 +40,352 @@ failure that no read has raised yet, unless another exception is already
|
|
|
40
40
|
propagating. `Files::File#read`, `#gets`, `#readline`, `#readpartial` and
|
|
41
41
|
`#each_line` read from `read_io` and raise the same way.
|
|
42
42
|
|
|
43
|
+
A response that carries `X-Files-Frontend-App` came from the Files.com web
|
|
44
|
+
app, such as a sign-in page, rather than from file storage. It raises
|
|
45
|
+
`Files::Transfer::FrontendResponseError` before any of it is written, and
|
|
46
|
+
closes the IO as a refused transfer does.
|
|
47
|
+
|
|
48
|
+
## Uploads
|
|
49
|
+
|
|
50
|
+
`upload_file` sends a file one part at a time, as the API grants each. A part
|
|
51
|
+
counts as uploaded only when storage answers it with a success (2xx); any
|
|
52
|
+
other status raises `Files::APIError` with the message `Transfer request
|
|
53
|
+
failed` and the status in `http_status`, before another part is planned or the
|
|
54
|
+
upload is finalized. This holds with or without `progress:`, and for
|
|
55
|
+
`upload_chunks` and `Files::File#write` and `#close`. (Before, without
|
|
56
|
+
`progress:`, a part answered with another status was treated as uploaded.)
|
|
57
|
+
|
|
58
|
+
## Adaptive transfers
|
|
59
|
+
|
|
60
|
+
Adaptive transfers send a file's parts, or fetch its ranges, several at once,
|
|
61
|
+
and tune how many are in flight to what the link sustains, within the limits
|
|
62
|
+
you set. They are opt-in: pass `transfer:` to
|
|
63
|
+
|
|
64
|
+
* `Files::File.upload_file`, the `upload_to_*` destinations, which pass it
|
|
65
|
+
on, and `Files::File#upload_file`, which uploads to the record's own path
|
|
66
|
+
with the record's own API options;
|
|
67
|
+
* `Files::File.upload_io`, for an IO or StringIO of yours, with its `size:`;
|
|
68
|
+
* `Files::File.download_file`, `Files::File#download_file` and
|
|
69
|
+
`Files::File#download_content` (not with `range:`).
|
|
70
|
+
|
|
71
|
+
Without `transfer:`, every method works one request at a time, as before, and
|
|
72
|
+
so does `upload_io` without `size:`, reading the IO to its end. `upload_chunks`,
|
|
73
|
+
`#write` and `#close` are never adaptive, and `read_io` refuses `transfer:`
|
|
74
|
+
with `Files::InvalidParameterError` before it starts anything.
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
Files::File.upload_file("report.bin", "reports/report.bin", transfer: true)
|
|
78
|
+
Files::File.upload_file("report.bin", "reports/report.bin", {}, progress: ->(part) { puts part[:acknowledged_bytes] },
|
|
79
|
+
transfer: { concurrency: 8 }
|
|
80
|
+
)
|
|
81
|
+
Files::File.upload_io(io, "reports/report.bin", {}, size: io_size, transfer: true)
|
|
82
|
+
Files::File.download_file("reports/report.bin", "report.bin", progress: ->(report) { puts report[:bytes_per_second] },
|
|
83
|
+
transfer: { max_concurrency: 16 }
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# One job shared by several transfers, from any threads.
|
|
87
|
+
Files::Transfer::Job.open(max_files: 2) do |job|
|
|
88
|
+
paths.map { |path| Thread.new { Files::File.upload_file(path, "reports/#{File.basename(path)}", transfer: job) } }.each(&:join)
|
|
89
|
+
end
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`transfer:` takes `true` for the defaults, a Hash of the options below, a
|
|
93
|
+
`Files::Transfer::Options`, or a `Files::Transfer::Job`. A Hash or `true`
|
|
94
|
+
makes a job for that one call. A shared job's transfers to the same storage
|
|
95
|
+
share what the job learns about it, all of them count against one
|
|
96
|
+
`buffer_bytes` and one limit of requests in flight (a fixed `concurrency`, or
|
|
97
|
+
`max_concurrency`, or 64), and at most `max_files` run at once; a transfer
|
|
98
|
+
opens its file only once it has its turn. Close a job you create with
|
|
99
|
+
`Files::Transfer::Job.new`, or use `Job.open` with a block. `close` waits at
|
|
100
|
+
most five seconds in all for transfers still running and their requests, and
|
|
101
|
+
raises `Files::Error` if any are still running then.
|
|
102
|
+
|
|
103
|
+
| Option | Values | Default |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| `concurrency` | `:automatic`, or an Integer from 1 to 256 that stays fixed | `:automatic` |
|
|
106
|
+
| `startup` | `:default` or `:aggressive`, only with `:automatic` | `:default` |
|
|
107
|
+
| `max_concurrency` | An Integer from 1 to 256, only with `:automatic` | 64, or 16 for a direct destination |
|
|
108
|
+
| `buffer_bytes` | An Integer of at least 65,536 | 256 MiB |
|
|
109
|
+
| `max_files` | A positive Integer | 4 |
|
|
110
|
+
| `control` | A `Files::Transfer::Control` | none |
|
|
111
|
+
|
|
112
|
+
An invalid option raises `Files::InvalidParameterError` before anything is
|
|
113
|
+
sent.
|
|
114
|
+
|
|
115
|
+
### How many requests are in flight
|
|
116
|
+
|
|
117
|
+
With `:automatic`, an upload to cloud storage starts with one part in flight
|
|
118
|
+
(`startup: :default`) and probes upward while each step pays off, or starts at
|
|
119
|
+
32 (`:aggressive`). Its first measured window warms the connection and its
|
|
120
|
+
second sets the baseline. From a baseline that is not already queueing it adds
|
|
121
|
+
about half again, waits until every request of the round that filled the new
|
|
122
|
+
limit has ended, and keeps the raise only when the next window's throughput
|
|
123
|
+
grew with it without its requests queueing; then it tries the next. A raise
|
|
124
|
+
that does not pay off goes back, and the upload rests for two windows before
|
|
125
|
+
trying one more, as it does from a queueing baseline; it keeps warming this
|
|
126
|
+
way until it reaches 32. A failure or throttle while warming gives up the
|
|
127
|
+
raise and rests, at whatever limit it left, which can go down to one. A link
|
|
128
|
+
that moves at least 96 MiB/s goes straight to 32. It then grows while
|
|
129
|
+
throughput rises, by 2 below 32 and by 1 above, between 4 and
|
|
130
|
+
`max_concurrency` (64 by default). It stops growing when its requests start to
|
|
131
|
+
queue, and shrinks by 8% (not below 12) when they queue further, by 35% after a
|
|
132
|
+
failure and by 10% after a throttle (a 429 or 503), not below 4. It judges
|
|
133
|
+
throughput only over windows in which at least 75% of the allowed requests
|
|
134
|
+
were on the network, so waiting on the API, the file, admission or memory
|
|
135
|
+
never counts as a slow link. When the API reports a direct destination (a
|
|
136
|
+
valid version 1 `direct_connection_info`), uploads start at 4, between 1 and
|
|
137
|
+
16, growing by 1. Downloads start at 32 ranges, between 4 and
|
|
138
|
+
`max_concurrency`. A fixed `concurrency` never changes. Fewer requests are in
|
|
139
|
+
flight whenever fewer parts remain. A warm start compares each window's
|
|
140
|
+
attempts by their median duration per byte, so parts of different sizes
|
|
141
|
+
compare alike, and sizes each probe's window from the variation seen so far.
|
|
142
|
+
A request counts against the limit from when it is admitted, but is on the
|
|
143
|
+
network only from when its send starts until it is answered: a part when its
|
|
144
|
+
response headers arrive, a range once its whole body has arrived and been
|
|
145
|
+
checked. Waiting for a worker, reading a part before its send, the API, your
|
|
146
|
+
callbacks and writing never count as network time. A request that succeeds
|
|
147
|
+
counts in the window it finishes in, even one sent before the limit last
|
|
148
|
+
changed.
|
|
149
|
+
|
|
150
|
+
`Job#diagnostics` reports `accepted_bytes` (bytes storage acknowledged or that
|
|
151
|
+
were received for writing, each counted once however often it was retried),
|
|
152
|
+
`elapsed_seconds`, `goodput_bytes_per_second`, `retries`, the requests in
|
|
153
|
+
flight and their limit, the bytes held, and for each controller its limit, the
|
|
154
|
+
requests it admitted (`admitted`) and those on the network (`inflight`), its
|
|
155
|
+
phase, `judged_windows`, `ineligible_windows` (windows not judged because too
|
|
156
|
+
few requests were on the network) and each decision, and `throttled`, each
|
|
157
|
+
origin a `Retry-After` holds back now with the seconds left. It holds no URLs
|
|
158
|
+
or credentials.
|
|
159
|
+
|
|
160
|
+
### Uploads
|
|
161
|
+
|
|
162
|
+
Parts are requested five at a time, and the API chooses their sizes, except
|
|
163
|
+
as below for Amazon S3. When an
|
|
164
|
+
upload begins, your thread resolves, from copies of your options, what every
|
|
165
|
+
API request of it then uses: the client (`options[:client]` or the thread's),
|
|
166
|
+
the credential (an `api_key` option, otherwise a `session_id` or `session`
|
|
167
|
+
option or `Files.session_id`, otherwise `Files.api_key`, or none), the origin
|
|
168
|
+
(`options[:base_url]` or `Files.base_url`), the `region_http_pairs`, the
|
|
169
|
+
workspace, and copies of `Files.default_headers`, `Files.language`,
|
|
170
|
+
`Files.app_info`, the timeouts, `Files.region_policy` and
|
|
171
|
+
`Files.region_handler`. A `default_headers` Proc and the region handler are
|
|
172
|
+
kept as they are, and still called for each request that needs them. Each
|
|
173
|
+
grant's answer then carries its own context, such as the regional origin a
|
|
174
|
+
lockout region mismatch moved the upload to, to the requests after it.
|
|
175
|
+
Changing your options, even in place, the thread's client, any of those
|
|
176
|
+
settings or the pairs from a callback cannot change what the upload's API
|
|
177
|
+
requests send, and a credential that was not set stays unset.
|
|
178
|
+
|
|
179
|
+
Through the SDK's own connection a part streams from the file and holds at
|
|
180
|
+
most 64 KiB in memory. A client you pass (`options[:client]`) with its own
|
|
181
|
+
adapter or middleware, its own `remote_request`, its own logger or log level,
|
|
182
|
+
or connection settings of its own, such as a minimum TLS version, an adapter
|
|
183
|
+
configuration block, or a proxy (with its user and password) other than the
|
|
184
|
+
one the job's own connections use, `Files.proxy` as it was when the job
|
|
185
|
+
began, keeps carrying the parts, one at a time and read
|
|
186
|
+
whole, so each part must fit `buffer_bytes`; a part that does not raises
|
|
187
|
+
`Files::Transfer::BufferLimitError` before it is read. Each part goes through
|
|
188
|
+
that client's `remote_request` exactly once, with its logging, hooks and
|
|
189
|
+
settings; the transfer alone retries it. `Job#diagnostics` notes when this
|
|
190
|
+
happens. The part's URL reaches the client's adapter as Ruby's `URI` parses
|
|
191
|
+
it, with none of the request's or the connection's default parameters added.
|
|
192
|
+
`URI` keeps the query's order, its percent escapes and the characters a signed
|
|
193
|
+
URL's query uses, so such a query arrives exactly as the API gave it, as its
|
|
194
|
+
signature needs; a space or another character `URI` does not keep in a query
|
|
195
|
+
is escaped, and tabs and line breaks are dropped. A URL `URI` cannot parse,
|
|
196
|
+
such as one with `%zz` in its query, is left to Faraday as it is.
|
|
197
|
+
|
|
198
|
+
`upload_io` with `size:` reads exactly `size` bytes of your IO on your thread,
|
|
199
|
+
part by part in order, as many reads as it takes, with `read(length)` alone.
|
|
200
|
+
It copies what each read returns before it reads again, so an IO whose reads
|
|
201
|
+
reuse one String still sends exactly what it read, and it never changes your
|
|
202
|
+
Strings. It reads a part only once `buffer_bytes` can hold all reading and
|
|
203
|
+
sending it may need, and keeps its copy through renewals and retries, until
|
|
204
|
+
storage acknowledges the part or the upload stops, so a retry sends the same
|
|
205
|
+
bytes and the bytes held never exceed `buffer_bytes`. Over the SDK's own
|
|
206
|
+
connection, a part read in pieces is sent from them through a 64 KiB slice,
|
|
207
|
+
so it needs its size and that slice more; through a client you pass, which
|
|
208
|
+
takes each part as one String, a part read in pieces is copied into one, so
|
|
209
|
+
it needs twice its size while it is read. That is reserved before anything of
|
|
210
|
+
the part is read, and what a single read of the whole part, or the String it
|
|
211
|
+
was copied into, doesn't need is given back once it is read; a part that
|
|
212
|
+
cannot have it raises `Files::Transfer::BufferLimitError` before it is read.
|
|
213
|
+
An IO that ends early raises `Files::Transfer::SourceChangedError`; nothing
|
|
214
|
+
past `size` is read, and the IO is never rewound or closed.
|
|
215
|
+
|
|
216
|
+
A part is acknowledged only by a 2xx response with exactly one nonempty ETag;
|
|
217
|
+
anything else raises `Files::APIError`. `progress` is called on your thread,
|
|
218
|
+
once for each acknowledged part, in the order storage acknowledged them, with
|
|
219
|
+
`total_bytes`, `acknowledged_bytes` (each part counted once), `part_number`,
|
|
220
|
+
`part_bytes`, `elapsed_seconds` of this call and `bytes_per_second`: the bytes
|
|
221
|
+
storage acknowledged during this call, a retried part's once, over those
|
|
222
|
+
seconds, or 0.0 when no time has passed. Another transfer of a shared job
|
|
223
|
+
never counts. A resume's `acknowledged_bytes` includes the parts acknowledged
|
|
224
|
+
before the pause, but its `elapsed_seconds` and `bytes_per_second` cover only
|
|
225
|
+
the resume call and the parts it acknowledged. The upload is finalized only
|
|
226
|
+
after every part is acknowledged and the local file still has the size and
|
|
227
|
+
modification time it had when opened; a change raises
|
|
228
|
+
`Files::Transfer::SourceChangedError`. A part whose instructions say
|
|
229
|
+
`parallel_parts: false` makes the file send one part at a time. Even with a
|
|
230
|
+
direct destination, parts go to the `upload_uri` the API gave.
|
|
231
|
+
|
|
232
|
+
The SDK sizes an upload's parts itself only when every part of the API's
|
|
233
|
+
first answer shows one ordinary multipart upload straight to Amazon S3:
|
|
234
|
+
`action` `put/write` with `PUT`; no `headers`, `parameters` or
|
|
235
|
+
`direct_connection_info`; instructions to send exactly the part's bytes as the
|
|
236
|
+
body with their `Content-Length`; and an `upload_uri` with `https` on the
|
|
237
|
+
default port, without user information or fragment, to an S3 general-purpose
|
|
238
|
+
endpoint (`s3`, `s3.<region>`, `s3-<region>` or `s3.dualstack.<region>` under
|
|
239
|
+
`amazonaws.com` or `amazonaws.com.cn`, with the bucket before it or in the
|
|
240
|
+
path), presigned with SigV4 for `s3` with only `host` signed, naming that
|
|
241
|
+
part's `partNumber` and the same `uploadId`, with no query parameter but those
|
|
242
|
+
and SigV4's own. Anything else, such as an S3-compatible service or another
|
|
243
|
+
host, an accelerate, FIPS or access point endpoint, an agent, a direct
|
|
244
|
+
connection, or a URL signing a length or checksum, keeps the API's sizes and
|
|
245
|
+
instructions, as does an empty file. `parallel_parts` decides only whether
|
|
246
|
+
parts go at once, never their size.
|
|
247
|
+
|
|
248
|
+
Such an upload's parts, but the last, are 8 MiB (8,388,608 bytes), or the
|
|
249
|
+
least whole number of MiB that fits the file in 10,000 parts, or in the first
|
|
250
|
+
part's `available_parts` when that is fewer; never under 5 MiB unless the file
|
|
251
|
+
is one part, nor over 1 GiB; for files of at most 5 TiB. These are the SDK's
|
|
252
|
+
own planning limits, not ones Files.com or S3 promise, and a file they cannot
|
|
253
|
+
plan keeps the API's sizes. Where `buffer_bytes` must hold a part, through a
|
|
254
|
+
client you pass or for `upload_io`, the parts are no larger than it can hold
|
|
255
|
+
unless the plan needs them larger, which raises
|
|
256
|
+
`Files::Transfer::BufferLimitError` before anything is read. So does a file of
|
|
257
|
+
at most 5 TiB that would need parts larger than 1 GiB to fit in the parts
|
|
258
|
+
available, when `buffer_bytes` cannot hold even the smallest of them: the
|
|
259
|
+
API's sizes could not be smaller. A pause that came before that refusal gives a
|
|
260
|
+
checkpoint with no sizes chosen, whose resume chooses them for its own
|
|
261
|
+
`buffer_bytes`. Each part keeps
|
|
262
|
+
its offset and size through renewals, retries and a resume, whatever
|
|
263
|
+
`partsize` or `next_partsize` the API recommends later, and is sent with
|
|
264
|
+
exactly its bytes and their `Content-Length` to the `upload_uri` the API gave.
|
|
265
|
+
A later part or a renewal that is not for the same S3 upload, in the same
|
|
266
|
+
form, raises `Files::APIError` before it is sent.
|
|
267
|
+
|
|
268
|
+
### Downloads
|
|
269
|
+
|
|
270
|
+
A download first asks for its opening range (8 MiB, or a quarter of
|
|
271
|
+
`buffer_bytes` when that is less). Ranges are fetched at once only when
|
|
272
|
+
storage answers with a strong ETag and exact `Content-Range` and
|
|
273
|
+
`Content-Length`; each later range is requested with `If-Match` and must
|
|
274
|
+
match exactly. A 412, or a whole response with another ETag, raises
|
|
275
|
+
`Files::Transfer::VersionChangedError` before any of it is written. Ranges are
|
|
276
|
+
written in order, and those waiting for an earlier one count against
|
|
277
|
+
`buffer_bytes`. A download looks up its URL, and renews it, with the API
|
|
278
|
+
options, credential, origin, workspace and settings it began with, from the
|
|
279
|
+
record's own options, as an upload does. Its requests for content go through
|
|
280
|
+
`Files::ApiClient.download_client` as your thread has it when the download
|
|
281
|
+
begins: over the job's own connections when it is the SDK's own client with
|
|
282
|
+
its default connection unchanged and made with the job's own proxy
|
|
283
|
+
(`Files.proxy` as it was when the job began), and otherwise through that
|
|
284
|
+
client's `remote_request`, once each, one request at a time, with its own
|
|
285
|
+
settings and proxy, and the URL as given, as an upload's parts are.
|
|
286
|
+
Through such a client each response is streamed as it arrives, through
|
|
287
|
+
Faraday's `on_data`, which only Faraday's `net_http` and
|
|
288
|
+
`net_http_persistent` adapters are relied on to do, with any options or
|
|
289
|
+
configuration block of their own. With any other adapter an adaptive download
|
|
290
|
+
raises `Files::Transfer::BufferLimitError` before it sends a content request
|
|
291
|
+
or writes anything; without `transfer:` it downloads as before.
|
|
292
|
+
|
|
293
|
+
Otherwise storage's whole response is written as it arrives. If it fails
|
|
294
|
+
partway, a retry starts again from the first byte: as the retry's first bytes
|
|
295
|
+
are written, `download_file` truncates its file, and an IO you passed is
|
|
296
|
+
truncated back to where the download began when it can `seek` and `truncate`;
|
|
297
|
+
otherwise the failure is raised instead of writing the same bytes twice. A
|
|
298
|
+
cancellation, a pause or a failed retry before then keeps what was written.
|
|
299
|
+
|
|
300
|
+
`progress`, a callable, is called on your thread after each write with
|
|
301
|
+
`total_bytes` (`nil` until known), `written_bytes`, `elapsed_seconds` of this
|
|
302
|
+
call and `bytes_per_second`, with the client an `ApiClient#request` block you
|
|
303
|
+
made the call in still active, whichever client carries the content. Anything
|
|
304
|
+
it raises ends the download. It needs `transfer:`.
|
|
305
|
+
|
|
306
|
+
Adaptive downloads write the bytes exactly as stored, without decompressing a
|
|
307
|
+
`Content-Encoding`. As without `transfer:`, a failure leaves what was written
|
|
308
|
+
in place; a refused transfer or a failing write closes an IO you passed, and
|
|
309
|
+
other failures leave it open. A refusal raises `Files::APIError` with
|
|
310
|
+
`http_status`; a lost connection or a short body raises its own error, such as
|
|
311
|
+
`EOFError`.
|
|
312
|
+
|
|
313
|
+
### Retries and expiry
|
|
314
|
+
|
|
315
|
+
Each part or range is retried up to `Files.max_network_retries` times, each
|
|
316
|
+
retry a new admission that gives back its request slot while it waits: after
|
|
317
|
+
100 ms for a network failure, a 500, 502 or 504, or S3's `RequestTimeout` (a
|
|
318
|
+
400 whose whole body, of at most 64 KiB, is exactly that XML error: a
|
|
319
|
+
well-formed document, with no DTD, namespace or repeated attribute, whose
|
|
320
|
+
`<Error>` root has a direct `<Code>RequestTimeout</Code>`); for a 429 or 503
|
|
321
|
+
after its whole `Retry-After`, however long, or at once without one. That
|
|
322
|
+
`Retry-After` also holds back every new request and retry to the same origin,
|
|
323
|
+
from all of the job's transfers, whether they go over the job's own
|
|
324
|
+
connections or through a client you passed, a download's opening request
|
|
325
|
+
included, until it has passed. It holds them back from before the throttled
|
|
326
|
+
request's slot is free for a request waiting for it; a later one can extend it
|
|
327
|
+
but not shorten it, and requests already sent finish. A cancellation or pause
|
|
328
|
+
still ends the wait
|
|
329
|
+
at once, and a `Retry-After` too large to schedule fails the transfer instead.
|
|
330
|
+
A 501, other 4xx or 3xx is not retried, nor is any part whose instructions say
|
|
331
|
+
`retry_parts: false`.
|
|
332
|
+
|
|
333
|
+
A signed URL within five seconds of its expiry, by the API's `expires` or the
|
|
334
|
+
URL's own signature parameters, is renewed before it is sent, at most twice;
|
|
335
|
+
one still expired after that fails the transfer without being sent. A URL
|
|
336
|
+
that expires after its request was sent is renewed and sent again only as one
|
|
337
|
+
of the part's retries, and never for `retry_parts: false`. An upload's renewal
|
|
338
|
+
must keep the part's reference, number, size (the SDK's own, for parts it
|
|
339
|
+
sizes, with the same S3 upload), method, headers and retry rules.
|
|
340
|
+
Each request goes to the URL it was admitted for, whose origin's `Retry-After`
|
|
341
|
+
held it back and which a throttle it meets holds back, even when a renewal
|
|
342
|
+
gives a new URL before it is sent; the requests admitted after a renewal use
|
|
343
|
+
the new one.
|
|
344
|
+
|
|
345
|
+
### Cancel, pause and resume
|
|
346
|
+
|
|
347
|
+
`Files::Transfer::Control#cancel` and `#pause`, from any thread, stop new
|
|
348
|
+
requests at once; the transfer then waits for the requests in flight, releases
|
|
349
|
+
what it holds and raises `Files::Transfer::CancelledError` or
|
|
350
|
+
`Files::Transfer::PausedError`. Whichever of a failure, a cancellation or a
|
|
351
|
+
pause happened first is the one raised, and nothing is finalized after it.
|
|
352
|
+
That holds while a transfer opens its file or destination, while a resume
|
|
353
|
+
checks them, while a download looks up its URL or waits for its opening
|
|
354
|
+
request too, and to its end: a cancellation from a download's last `progress`
|
|
355
|
+
call is raised, not a success.
|
|
356
|
+
|
|
357
|
+
`PausedError#checkpoint` resumes with `Files::File.resume_upload(checkpoint,
|
|
358
|
+
options)` or `Files::File.resume_download(checkpoint, io, options)`, passing
|
|
359
|
+
the API options again. A checkpoint resumes only in the process that paused,
|
|
360
|
+
one resume at a time, and cannot be dumped. Once a resume has checked the
|
|
361
|
+
local file or destination and starts its transfer, the checkpoint is spent,
|
|
362
|
+
however the transfer ends; pause it again for a new one. Only a resume refused
|
|
363
|
+
before it started, or paused or cancelled before it finished checking them,
|
|
364
|
+
even when the check then fails, leaves the checkpoint usable. It holds no credentials,
|
|
365
|
+
signed URLs, API options or record attributes: of an upload's parameters only
|
|
366
|
+
`mkdir_parents`, `with_rename` and `size`, of each part's instructions
|
|
367
|
+
only a digest, and of an upload whose parts the SDK sizes, that size and a
|
|
368
|
+
SHA-256 digest of its S3 object URL, without the query, and `uploadId`; it
|
|
369
|
+
resumes with the same sizes and S3 upload. Resuming raises `Files::Transfer::CheckpointError`, before
|
|
370
|
+
anything is sent, written or truncated, when the local file, the
|
|
371
|
+
downloaded-to file or the IO is not the one the checkpoint was taken from, or
|
|
372
|
+
the bytes already downloaded into it changed. Those bytes are read back, a
|
|
373
|
+
slice at a time charged to `buffer_bytes`, and checked by a SHA-256 digest:
|
|
374
|
+
from a local file, a StringIO, or an IO you passed that can give them back
|
|
375
|
+
(with `pread`, by seeking back, or through its path), such as a File or a
|
|
376
|
+
Tempfile; an IO that cannot is refused. Anything after them is dropped only
|
|
377
|
+
once storage's answer proves the version: as the first new bytes are written,
|
|
378
|
+
or, when every byte was written before the pause, once storage answers for
|
|
379
|
+
the file's last byte with that version. A download stops with
|
|
380
|
+
`VersionChangedError` when storage no longer has its version, leaving the
|
|
381
|
+
destination as it was, and an upload stops when a renewed part's instructions
|
|
382
|
+
differ. A download without a strong ETag resumes from its first byte, and its
|
|
383
|
+
checkpoint is `nil` when it went to an IO that can neither start over nor say
|
|
384
|
+
where its bytes began. A transfer paused before it started, or while it opened
|
|
385
|
+
its local file or destination, also has none, and sent no content request (a
|
|
386
|
+
resume paused then gives back the checkpoint it was given), nor does an
|
|
387
|
+
`upload_io` stream, which cannot be read again.
|
|
388
|
+
|
|
43
389
|
## Example File Object
|
|
44
390
|
|
|
45
391
|
```
|
data/lib/files.com/api.rb
CHANGED
|
@@ -8,7 +8,10 @@ module Files
|
|
|
8
8
|
# region_http_pairs the request used, only after the request, and that
|
|
9
9
|
# check, succeed; the caller's options are not changed. An options base_url
|
|
10
10
|
# sends the request there instead of to Files.base_url, and an options
|
|
11
|
-
# region_http_pairs is used instead of the client's.
|
|
11
|
+
# region_http_pairs is used instead of the client's. An options
|
|
12
|
+
# request_settings, which an adaptive transfer fixes as it begins
|
|
13
|
+
# (ApiClient.transfer_settings), is used instead of the library-wide
|
|
14
|
+
# settings; it is never sent as a header, nor kept in the returned options.
|
|
12
15
|
#
|
|
13
16
|
# @param path [String] API endpoint path.
|
|
14
17
|
# @param verb [Symbol] HTTP method.
|
|
@@ -36,6 +39,7 @@ module Files
|
|
|
36
39
|
region_http_pairs = headers.delete(:region_http_pairs)
|
|
37
40
|
session_id = headers.delete(:session_id)
|
|
38
41
|
workspace_id = headers.delete(:workspace_id)
|
|
42
|
+
settings = headers.delete(:request_settings)
|
|
39
43
|
if session = headers.delete(:session)
|
|
40
44
|
session.save unless session.id
|
|
41
45
|
session_id = session.id
|
|
@@ -45,6 +49,7 @@ module Files
|
|
|
45
49
|
# Only an origin or pairs the request carries are passed on; without them the client uses its own as before.
|
|
46
50
|
request_options[:base_url] = base_url unless base_url.nil?
|
|
47
51
|
request_options[:region_http_pairs] = region_http_pairs unless region_http_pairs.nil?
|
|
52
|
+
request_options[:settings] = settings unless settings.nil?
|
|
48
53
|
regional_base_url = nil
|
|
49
54
|
resp, api_key, session_id = client.execute_request(verb, path, **request_options) do |origin, used_region_http_pairs|
|
|
50
55
|
regional_base_url = origin
|