@@ -62,6 +62,15 @@ extension ModelDownloadTask {
62
62
}
63
63
64
64
func download( progressHandler: ProgressHandler ? , completion: @escaping Completion ) {
65
+ /// Prevent multiple concurrent downloads.
66
+ guard downloadStatus == . notStarted else {
67
+ completion ( . failure( . internalError( description: ModelDownloadTask . ErrorDescription
68
+ . anotherDownloadInProgress) ) )
69
+ DeviceLogger . logEvent ( level: . debug,
70
+ message: ModelDownloadTask . ErrorDescription. anotherDownloadInProgress,
71
+ messageCode: . anotherDownloadInProgressError)
72
+ return
73
+ }
65
74
downloader. downloadFile ( with: remoteModelInfo. downloadURL,
66
75
progressHandler: { downloadedBytes, totalBytes in
67
76
/// Fraction of model file downloaded.
@@ -70,6 +79,10 @@ extension ModelDownloadTask {
70
79
} ) { result in
71
80
switch result {
72
81
case let . success( response) :
82
+ DeviceLogger . logEvent ( level: . debug,
83
+ message: ModelDownloadTask . DebugDescription
84
+ . receivedServerResponse,
85
+ messageCode: . validModelDownloadResponse)
73
86
self . handleResponse (
74
87
response: response. urlResponse,
75
88
tempURL: response. fileURL,
@@ -79,20 +92,31 @@ extension ModelDownloadTask {
79
92
var downloadError : DownloadError
80
93
switch error {
81
94
case let FileDownloaderError . networkError( error) :
82
- downloadError = . internalError( description: ModelDownloadTask
83
- . ErrorDescription
84
- . invalidHostName ( error
85
- . localizedDescription) )
95
+ let description = ModelDownloadTask . ErrorDescription
96
+ . invalidHostName ( error. localizedDescription)
97
+ downloadError = . internalError( description: description)
98
+ DeviceLogger . logEvent ( level: . debug,
99
+ message: description,
100
+ messageCode: . hostnameError)
86
101
// TODO: Handle this case better.
87
102
case FileDownloaderError . sessionInvalidated:
88
103
downloadError = . failedPrecondition
104
+ DeviceLogger . logEvent ( level: . debug,
105
+ message: ModelDownloadTask . ErrorDescription. sessionInvalidated,
106
+ messageCode: . invalidDownloadSessionError)
89
107
case FileDownloaderError . unexpectedResponseType:
90
- downloadError = . internalError( description: ModelDownloadTask
91
- . ErrorDescription. invalidServerResponse)
108
+ let description = ModelDownloadTask . ErrorDescription. invalidServerResponse
109
+ downloadError = . internalError( description: description)
110
+ DeviceLogger . logEvent ( level: . debug,
111
+ message: description,
112
+ messageCode: . invalidResponseError)
92
113
93
114
default :
94
- downloadError = . internalError( description: ModelDownloadTask . ErrorDescription
95
- . unknownDownloadError)
115
+ let description = ModelDownloadTask . ErrorDescription. unknownDownloadError
116
+ downloadError = . internalError( description: description)
117
+ DeviceLogger . logEvent ( level: . debug,
118
+ message: description,
119
+ messageCode: . modelDownloadError)
96
120
}
97
121
completion ( . failure( downloadError) )
98
122
}
@@ -104,9 +128,14 @@ extension ModelDownloadTask {
104
128
guard ( 200 ..< 299 ) . contains ( response. statusCode) else {
105
129
/// Possible failure due to download URL expiry.
106
130
if response. statusCode == 400 {
107
- completion ( . failure( . failedPrecondition ) )
131
+ completion ( . failure( . expiredDownloadURL ) )
108
132
return
109
133
}
134
+ let description = ModelDownloadTask . ErrorDescription. modelDownloadFailed ( response. statusCode)
135
+ DeviceLogger . logEvent ( level: . debug,
136
+ message: description,
137
+ messageCode: . modelDownloadError)
138
+ completion ( . failure( . internalError( description: description) ) )
110
139
return
111
140
}
112
141
@@ -117,10 +146,16 @@ extension ModelDownloadTask {
117
146
118
147
do {
119
148
try ModelFileManager . moveFile ( at: tempURL, to: modelFileURL)
149
+ DeviceLogger . logEvent ( level: . debug,
150
+ message: ModelDownloadTask . DebugDescription. savedModelFile,
151
+ messageCode: . downloadedModelFileSaved)
120
152
/// Generate local model info.
121
153
let localModelInfo = LocalModelInfo ( from: remoteModelInfo, path: modelFileURL. absoluteString)
122
154
/// Write model to user defaults.
123
155
localModelInfo. writeToDefaults ( defaults, appName: appName)
156
+ DeviceLogger . logEvent ( level: . debug,
157
+ message: ModelDownloadTask . DebugDescription. savedLocalModelInfo,
158
+ messageCode: . downloadedModelInfoSaved)
124
159
/// Build model from model info.
125
160
let model = CustomModel ( localModelInfo: localModelInfo)
126
161
downloadStatus = . successful
@@ -154,7 +189,9 @@ extension ModelDownloadTask {
154
189
extension ModelDownloadTask {
155
190
/// Debug descriptions.
156
191
private enum DebugDescription {
157
- static let modelSaved = " Model saved successfully to device. "
192
+ static let savedModelFile = " Model file saved successfully to device. "
193
+ static let savedLocalModelInfo = " Downloaded model info saved successfully to user defaults. "
194
+ static let receivedServerResponse = " Received a valid response from server. "
158
195
}
159
196
160
197
/// Error descriptions.
@@ -163,10 +200,16 @@ extension ModelDownloadTask {
163
200
" Unable to resolve hostname or connect to host: \( error) "
164
201
}
165
202
203
+ static let modelDownloadFailed = { ( code: Int ) in
204
+ " Model download failed with HTTP error code: \( code) "
205
+ }
206
+
207
+ static let sessionInvalidated = " Session invalidated due to failed pre-conditions. "
166
208
static let invalidServerResponse =
167
- " Could not get server response for model downloading. "
209
+ " Could not get valid server response for model downloading. "
168
210
static let unknownDownloadError = " Unable to download model due to unknown error. "
169
211
static let saveModel = " Unable to save downloaded remote model file. "
170
212
static let expiredModelInfo = " Unable to update expired model info. "
213
+ static let anotherDownloadInProgress = " Download already in progress. "
171
214
}
172
215
}
0 commit comments