speedup global inbox, implement global drafts/spam/trash

master
Vitaliy Filippov 2016-10-09 17:48:47 +03:00
parent 9dd0c44dc1
commit 4ec979569b
3 changed files with 39 additions and 19 deletions

View File

@ -48,7 +48,8 @@ Syncer.prototype.addAccount = function*(account)
name: account.name,
email: account.email,
settings: {
imap: account.imap
imap: account.imap,
folders: account.folders
}
}).returning('*').row(gen.ef());
}
@ -447,7 +448,9 @@ Syncer.prototype.addMessage = function*(boxId, msgrow, attrs)
msgrow.time = header.date;
msgrow.size = attrs.size;
if (!header.headers.received || !header.headers.received.length)
msgrow.flags.push('sent');
msgrow.flags.push('out');
else
msgrow.flags.push('in');
msgrow.flags = toPgArray(msgrow.flags);
msgrow.refs = toPgArray(header.references);
for (let i in msgrow)

View File

@ -109,13 +109,26 @@ SyncerWeb.prototype.msgSearchCond = function(query)
else if (query.folderType == 'pinned')
p = this.pg.sql('(flags @> array[\'flagged\']::varchar(255)[])');
else if (query.folderType == 'inbox')
p = this.pg.sql('not (flags @> array[\'sent\']::varchar(255)[])');
else if (query.folderType == 'sent')
p = this.pg.sql('(flags @> array[\'sent\']::varchar(255)[])');
p = this.pg.sql('(flags @> array[\'in\']::varchar(255)[])');
else if (query.folderType == 'out')
p = this.pg.sql('(flags @> array[\'out\']::varchar(255)[])');
else if (query.folderType == 'outbox')
{
// TODO это какая-то хитрая метапапка, которая не живёт на IMAP'е?
p = null;
}
else if (query.folderType == 'drafts' || query.folderType == 'spam' || query.folderType == 'trash')
p = null;
{
var folders = [];
var n;
for (var id in this.syncer.accounts)
{
n = this.syncer.accounts[id].settings.folders[query.folderType];
if (n)
folders.push(this.pg.sql.and({ 'f.name': n, 'f.account_id': id }));
}
p = this.pg.sql.or.apply(this.pg.sql.or, folders);
}
if (p && query.accountId)
p = this.pg.sql.and(p, this.pg.sql.eq('f.account_id', query.accountId));
return p;
@ -161,12 +174,12 @@ SyncerWeb.prototype.get_groups = function*(req, res)
.where(cond)
.groupBy('1, 2')
.union(
this.pg.select('date_part(\'year\', m.time)::text as name, date_part(\'year\', m.time)::text||\'-01-01\' date, count(*) count')
.from('messages m')
.innerJoin('folders f', this.pg.sql('f.id=m.folder_id'))
.where(cond)
.where(this.pg.sql.lt('m.time', intervals[0].date))
.groupBy('1, 2')
this.pg.select('y::text as name, y||\'-01-01\' date, ('+
this.pg.select('count(*)').from('messages m')
.innerJoin('folders f', this.pg.sql('f.id=m.folder_id'))
.where(cond).where(this.pg.sql('m.time >= (t.y||\'-01-01\')::date and m.time <= (t.y||\'-12-31\')::date'))
+') count')
.from('generate_series(1970, '+(today.getFullYear()-1)+') as t (y)')
)
.orderBy('date desc').rows(gen.ef());
return res.send({ groups: groups });
@ -199,13 +212,13 @@ SyncerWeb.prototype.get_message = function*(req, res)
if (this.cfg.login && (!req.session || !req.session.auth))
return res.sendStatus(401);
var msgId = req.query.msgId;
console.log('fetch message '+msgId);
var [ msg ] = yield this.pg.select('m.*, f.name folder_name, f.account_id')
.from('messages m').join('folders f', this.pg.sql('f.id=m.folder_id'))
.where({ 'm.id': msgId }).rows(gen.ef());
if (!msg.length)
return res.send({ error: 'not-found' });
msg = msg[0];
delete msg.text_index;
if (!msg.body_html && !msg.body_text)
{
var srv = yield* this.syncer.imap.getConnection(msg.account_id, msg.folder_name);

16
db.sql
View File

@ -5,11 +5,7 @@ create table accounts (
name varchar(255) not null,
email varchar(255) not null,
settings jsonb not null
-- настройки: replyto, cc, bcc, in_server, in_port, out_server, out_port, login, password
-- sent_folder, trash_folder, spam_folder, drafts_folder
-- in_server varchar(255) not null,
-- out_server varchar(255) not null,
-- reply_to
-- настройки: replyto, cc, bcc, imap, smtp, folders
);
create unique index accounts_email on accounts (email);
@ -46,7 +42,15 @@ create unique index messages_unique on messages (folder_id, uid);
create index messages_flags on messages using gin (folder_id, flags);
create index messages_messageid on messages (messageid);
create index messages_refs on messages using gin (refs);
create index messages_time on messages (folder_id, time);
create index messages_folder_id_time on messages (folder_id, time);
create index messages_time on messages (time);
-- create or replace function immutable_year(d timestamptz) returns text
-- language plpgsql immutable as $$
-- begin
-- return date_part('year', d);
-- end
-- $$;
-- create index messages_year on messages (immutable_year(time));
create or replace function messages_fulltext(msg messages) returns tsvector
language plpgsql immutable as $$
begin