2017-08-12 7 views
0

は、我々は実際の画像ファイルにファイルシステムのURLを保存するプロパティurlを持っているコアデータのエンティティImageを、持っているとしましょう。私たちは、このように削除機能を実装することができます:save()removeItem(at:)の両方が成功している原子的に削除データベース・エンティティとファイル

func deleteImage(_ image: Image) { 
    do { 
     let url = image.url 
     delete(image) 
     try save() 
     try FileManager.default.removeItem(at: url) 
    } catch { 
     rollback() 
    } 
} 
  • 場合、操作は成功です。
  • save()に失敗した場合、データベースは元の状態にロールバックされます。
  • ただし、save()は成功しましたが、removeItem(at:)に失敗した場合、孤児ファイルはファイルシステムに残されます。

別のプロセスのチェックを含む、定期的に孤立ファイルを削除せず、deleteImage()はアトミックにする方法はありますか?

-

100%の信頼性isDeletableFile(atPath:)を使用することが可能であるが、それでもません。ファイル・システムまたはファイルシステム上の特定のファイルの現在の状態に基づいて動作を述語しよう

func isDeletableFile(atPath path: String) -> Bool

推奨されません。そうすると、奇妙な動作や競合状態が発生する可能性があります。 (ファイルのロードやディレクトリの作成などの)操作を試み、エラーをチェックし、エラーが正常に処理されるようにするのは、操作が成功するかどうかを事前に把握するよりもはるかに優れています。

+0

なぜ削除する前に何かを保存しようとしていますか?とにかく、save()に "guard"を使うことができます: guard try save()else { "ここでエラーを投げます" } – Woof

+0

コアデータは 'save()'を呼び出す必要があります。データベースから実際にエンティティを削除します。また、 'guard 'を使うことは状況3を助けません。 –

答えて

0

A本当にアトミック削除を達成するのは非常に困難ですが、文の順序を少し変更した場合、あなたはかなりのコードの安定性を向上させることができます

  1. データベース内の画像を削除します。 。
  2. 成功した場合は、ファイルを一時フォルダに移動します。
  3. 成功した場合は、コミットします。
  4. 成功すると、一時フォルダ内のファイルを削除し、元の場所にファイルを戻します。

操作は1または2がロールバックよりも成功していない場合。 4の最初の部分は本当に必要ではなく、一時的なフォルダを特定の時点(たとえば、プログラムの開始、バックグラウンドからの復帰など)できれいにするか、または消去する必要があります。いくつかのまれな状況では、4のelse部分が失敗し、矛盾した状態になることがあります。

より複雑な変更は、アトミックな削除につながる可能性があります。オブジェクトは削除せず、削除済みとしてマークします。 2番目のステップでは、最初にファイルが存在する場合はそれを削除します。この2番目の手順は、削除するたびに、および特定の時点で適用することができます。このソリューションの欠点は、すべてのデータアクセスで削除されたオブジェクトを考慮する必要があるためです。

関連する問題