about summary refs log tree commit diff
path: root/app/javascript/mastodon/db/modifier.js
blob: eb951905a56be27c684e220085c2f10895ea3e30 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import asyncDB from './async';

const limit = 1024;

function put(name, objects, callback) {
  asyncDB.then(db => {
    const putTransaction = db.transaction(name, 'readwrite');
    const putStore = putTransaction.objectStore(name);
    const putIndex = putStore.index('id');

    objects.forEach(object => {
      function add() {
        putStore.add(object);
      }

      putIndex.getKey(object.id).onsuccess = retrieval => {
        if (retrieval.target.result) {
          putStore.delete(retrieval.target.result).onsuccess = add;
        } else {
          add();
        }
      };
    });

    putTransaction.oncomplete = () => {
      const readTransaction = db.transaction(name, 'readonly');
      const readStore = readTransaction.objectStore(name);

      readStore.count().onsuccess = count => {
        const excess = count.target.result - limit;

        if (excess > 0) {
          readStore.getAll(null, excess).onsuccess =
            retrieval => callback(retrieval.target.result.map(({ id }) => id));
        }
      };
    };
  });
}

export function evictAccounts(ids) {
  asyncDB.then(db => {
    const transaction = db.transaction(['accounts', 'statuses'], 'readwrite');
    const accounts = transaction.objectStore('accounts');
    const accountsIdIndex = accounts.index('id');
    const accountsMovedIndex = accounts.index('moved');
    const statuses = transaction.objectStore('statuses');
    const statusesIndex = statuses.index('account');

    function evict(toEvict) {
      toEvict.forEach(id => {
        accountsMovedIndex.getAllKeys(id).onsuccess =
          ({ target }) => evict(target.result);

        statusesIndex.getAll(id).onsuccess =
          ({ target }) => evictStatuses(target.result.map(({ id }) => id));

        accountsIdIndex.getKey(id).onsuccess =
          ({ target }) => target.result && accounts.delete(target.result);
      });
    }

    evict(ids);
  });
}

export function evictStatus(id) {
  return evictStatuses([id]);
}

export function evictStatuses(ids) {
  asyncDB.then(db => {
    const store = db.transaction('statuses', 'readwrite').objectStore('statuses');
    const idIndex = store.index('id');
    const reblogIndex = store.index('reblog');

    ids.forEach(id => {
      reblogIndex.getAllKeys(id).onsuccess =
        ({ target }) => target.result.forEach(reblogKey => store.delete(reblogKey));

      idIndex.getKey(id).onsuccess =
        ({ target }) => target.result && store.delete(target.result);
    });
  });
}

export function putAccounts(records) {
  put('accounts', records, evictAccounts);
}

export function putStatuses(records) {
  put('statuses', records, evictStatuses);
}