[name=makicamel]
Ruby では Hash のイテレーション中に Hash に破壊的変更として新しいキーを挿入しようとするとエラーになる ref can't add a new key into hash during iterationが謎の状況で発生しているように見えるときは - 猫型の蓄音機は 1 分間に 45 回にゃあと鳴く
hash = { a: :b }
hash.each do |_k, _v|
hash[:new_key] = :new_value
end
# (irb):3:in `block in <main>': can't add a new key into hash during iteration (RuntimeError)
# from (irb):2:in `each'
# from (irb):2:in `<main>'
# from /Users/makicamel/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>'
# from /Users/makicamel/.rbenv/versions/3.0.3/bin/irb:23:in `load'
# from /Users/makicamel/.rbenv/versions/3.0.3/bin/irb:23:in `<main>'
Set でも同様に発生する(Array では起きない)。これは Ruby の Set が内部記憶として Hash を使うため(ref)。
コード例
set = Set.new([1])
set.each do |_|
set << :new_value
end
# /Users/makicamel/.rbenv/versions/3.0.3/lib/ruby/3.0.0/set.rb:355:in `add': can't add a new key into hash during iteration (RuntimeError)
# from (irb):3:in `block in <main>'
# from /Users/makicamel/.rbenv/versions/3.0.3/lib/ruby/3.0.0/set.rb:344:in `each_key'
# from /Users/makicamel/.rbenv/versions/3.0.3/lib/ruby/3.0.0/set.rb:344:in `each'
# from (irb):2:in `<main>'
# from /Users/makicamel/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>'
# from /Users/makicamel/.rbenv/versions/3.0.3/bin/irb:23:in `load'
# from /Users/makicamel/.rbenv/versions/3.0.3/bin/irb:23:in `<main>'
array = [1]
array.each do |_|
array << :new_value
break
end
p array
# => [1, :new_value]
Coverband5.2.1 + 5.2.1.rc.1 で以下の不具合があった(master では修正済) can't add a new key into hash during iteration · Issue #436 · danmayer/coverband
# `@views_to_record` は Set なので他スレッドが `@views_to_record` に値を加えようとするとエラーになる
@views_to_record.each do |file|
redis_store.hset(tracker_key, file, reported_time)
end
マルチスレッドによるエラーは以下のコードで再現できる
set = Set.new((1..100).to_a)
Thread.new do
set.each do |_|
sleep(0.1)
end
end
Thread.new do
set << 101
end
# #<Thread:0x00007f8b3b8d4cd0 (irb):9 run> terminated with exception (report_on_exception is true):
# /Users/makicamel/.rbenv/versions/3.0.3/lib/ruby/3.0.0/set.rb:355:in `add': can't add a new key into hash during iteration (RuntimeError)
# from (irb):10:in `block in <main>'
[name=ken3ypa]
前回のFileSystemAccessAPI
を調べている際に、FileSystemHandleオブジェクトをIndexedDBに保存することでブラウザを閉じたあとも永続化できるという記載があった。そのためIndexedDBについて調査した
- JavaScript経由でクライアント側で永続的なデータベースにデータを保存・読み出しが出来る。
- オブジェクトストア(テーブル)を作成し、
- LocalStorageやSessionStorageなどの Web Storage より高度な機能を提供
- IndexやTransaction もサポートしている
- 2022/01/16現在、IndexedDB 2.0 が利用可能
- Chromeでは 58 から対応
- オブジェクトストアやインデックスの名前変更や getKey() などのメソッドが追加
- IndexedDB 3.0 も準備されつつある
- IE以外のブラウザの最新版であれば大体利用可能https://caniuse.com/indexeddb2
- WebStorageはユーザーのローカル環境(ブラウザ)にデータを保存するための仕組み。Cookieよりも保存できる容量が大きい(5MB)
- SessionStorage
- 保存されたデータはセッションの終了時に消える。セッションはブラウザを開いている限り持続する。 ただし新しいタブやウィンドウを開くと、新しいセッションが開始される。
- LocalStorage
- 保存されたデータに保持期間の制限はなく、新しいタブやウィンドウを開いてもセッションは持続する。
- SessionStorage
名前 | 型 | transaction | index | 容量 | 永続化 |
---|---|---|---|---|---|
LocalStorage | stringのみ | なし | なし | 1オリジンあたり5MB | あり |
SessionStorage | stringのみ | なし | なし | 1オリジンあたり5MB | ウィンドウやタブを閉じるまで |
IndexedDB | string, integer, floatなど複数の型をサポート | あり | あり | 許可なしで10MB 許可するとブラウザごとに決められた容量まで |
あり |
- グローバルリミット
- 最大容量は、ディスク空き容量の50% に決められる(たとえば500GBの容量があればブラウザのストレージサイズは250GB)
- 上限に達すると「オリジン立ち退き」を実行してストレージの総量が上限を下回るまでデータを削除
- グループリミット
- オリジンごとに、グローバルリミットの20%として決められる(250GBであれば50GB)
- グループリミットの場合は「オリジン立ち退き」は実行されない
- Chromeでは66から 2GB またはグローバルリミットの10% までの容量が適用される
- オリジンごとに、グローバルリミットの20%として決められる(250GBであれば50GB)
- StorageManager API を利用する
if (navigator.storage && navigator.storage.estimate) {
const quota = await navigator.storage.estimate();
// quota.usage -> Number of bytes used.
// quota.quota -> Maximum number of bytes available.
const percentageUsed = (quota.usage / quota.quota) * 100;
console.log(`You've used ${percentageUsed}% of the available storage.`);
const remaining = quota.quota - quota.usage;
console.log(`You can write up to ${remaining} more bytes.`);
}
typeof quota
// => 'object'
https://web.dev/storage-for-the-web/#check
2:DevTool -> Application -> Storage から確認