annotate libervia/backend/memory/sqla.py @ 4370:0eaa50f21efb

plugin XEP-0461: Message Replies implementation: Implement message replies. Thread ID are always added when a reply is initiated from Libervia, so a thread can continue the reply. rel 457
author Goffi <goffi@goffi.org>
date Tue, 06 May 2025 00:34:01 +0200
parents 2bdf0c16d852
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
2
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # Libervia: an XMPP client
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
5
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # (at your option) any later version.
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
10
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
15
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
18
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
19 import asyncio
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
20 from asyncio.subprocess import PIPE
3673
bd13391ee29e core (memory/sqla): fix `fileUpdate`
Goffi <goffi@goffi.org>
parents: 3665
diff changeset
21 import copy
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
22 from datetime import datetime
4212
5f2d496c633f core: get rid of `pickle`:
Goffi <goffi@goffi.org>
parents: 4160
diff changeset
23 import json
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
24 from pathlib import Path
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
25 import sys
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
26 import time
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
27 from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
28
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
29 from alembic import config as al_config, script as al_script
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
30 from alembic.runtime import migration as al_migration
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
31 from sqlalchemy import and_, delete, event, func, or_, update
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
32 from sqlalchemy import Integer, literal_column, text
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
33 from sqlalchemy.dialects.sqlite import insert
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
34 from sqlalchemy.engine import Connection, Engine
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
35 from sqlalchemy.exc import IntegrityError, NoResultFound
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
36 from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
37 from sqlalchemy.future import select
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
38 from sqlalchemy.orm import (
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
39 contains_eager,
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
40 joinedload,
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
41 selectinload,
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
42 sessionmaker,
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
43 subqueryload,
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
44 )
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
45 from sqlalchemy.orm.attributes import Mapped
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
46 from sqlalchemy.orm.decl_api import DeclarativeMeta
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
47 from sqlalchemy.sql.functions import coalesce, count, now, sum as sum_
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
48 from twisted.internet import defer
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
49 from twisted.words.protocols.jabber import jid
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
50 from twisted.words.xish import domish
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
51
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
52 from libervia.backend.core import exceptions
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
53 from libervia.backend.core.constants import Const as C
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
54 from libervia.backend.core.core_types import SatXMPPEntity
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
55 from libervia.backend.core.i18n import _
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
56 from libervia.backend.core.log import getLogger
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
57 from libervia.backend.memory import migration
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
58 from libervia.backend.memory import sqla_config
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
59 from libervia.backend.memory.sqla_mapping import (
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
60 Base,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
61 Component,
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
62 File,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
63 History,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
64 Message,
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
65 NOT_IN_EXTRA,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
66 Notification,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
67 NotificationPriority,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
68 NotificationStatus,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
69 NotificationType,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
70 ParamGen,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
71 ParamInd,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
72 PrivateGen,
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
73 PrivateGenBin,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
74 PrivateInd,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
75 PrivateIndBin,
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
76 Profile,
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
77 PubsubItem,
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
78 PubsubNode,
3893
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
79 Subject,
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
80 SyncState,
045af0eeda3f core, CLI (base), tools (common/data_format): typing/core readability
Goffi <goffi@goffi.org>
parents: 3862
diff changeset
81 Thread,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
82 get_profile_by_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
83 profiles,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
84 )
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
85 from libervia.backend.tools.common import uri
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
86 from libervia.backend.tools.utils import aio, as_future
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
87
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
88
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
89 log = getLogger(__name__)
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
90 migration_path = Path(migration.__file__).parent
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
91 #: mapping of Libervia search query operators to SQLAlchemy method name
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
92 OP_MAP = {
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
93 "==": "__eq__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
94 "eq": "__eq__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
95 "!=": "__ne__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
96 "ne": "__ne__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
97 ">": "__gt__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
98 "gt": "__gt__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
99 "<": "__le__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
100 "le": "__le__",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
101 "between": "between",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
102 "in": "in_",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
103 "not_in": "not_in",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
104 "overlap": "in_",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
105 "ioverlap": "in_",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
106 "disjoint": "in_",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
107 "idisjoint": "in_",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
108 "like": "like",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
109 "ilike": "ilike",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
110 "not_like": "notlike",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
111 "not_ilike": "notilike",
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
112 }
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
113
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
114
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
115 @event.listens_for(Engine, "connect")
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
116 def set_sqlite_pragma(dbapi_connection, connection_record):
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
117 cursor = dbapi_connection.cursor()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
118 cursor.execute("PRAGMA foreign_keys=ON")
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
119 cursor.close()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
120
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
121
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
122 class Storage:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
123
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
124 def __init__(self):
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
125 self.initialized = defer.Deferred()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
126 # we keep cache for the profiles (key: profile name, value: profile id)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
127 # profile id to component entry point
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
128 self.components: Dict[int, str] = {}
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
129
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
130 @property
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
131 def profiles(self):
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
132 return profiles
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
133
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
134 def get_profile_by_id(self, profile_id):
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
135 return get_profile_by_id(profile_id)
3665
72b0e4053ab0 core (memory/slqa): implement `getProfileById`
Goffi <goffi@goffi.org>
parents: 3664
diff changeset
136
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
137 async def migrate_apply(self, *args: str, log_output: bool = False) -> None:
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
138 """Do a migration command
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
139
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
140 Commands are applied by running Alembic in a subprocess.
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
141 Arguments are alembic executables commands
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
142
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
143 @param log_output: manage stdout and stderr:
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
144 - if False, stdout and stderr are buffered, and logged only in case of error
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
145 - if True, stdout and stderr will be logged during the command execution
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
146 @raise exceptions.DatabaseError: something went wrong while running the
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
147 process
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
148 """
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
149 stdout, stderr = 2 * (None,) if log_output else 2 * (PIPE,)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
150 proc = await asyncio.create_subprocess_exec(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
151 sys.executable,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
152 "-m",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
153 "alembic",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
154 *args,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
155 stdout=stdout,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
156 stderr=stderr,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
157 cwd=migration_path,
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
158 )
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
159 log_out, log_err = await proc.communicate()
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
160 if proc.returncode != 0:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
161 msg = _("Can't {operation} database (exit code {exit_code})").format(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
162 operation=args[0], exit_code=proc.returncode
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
163 )
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
164 if log_out or log_err:
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
165 msg += f":\nstdout: {log_out.decode()}\nstderr: {log_err.decode()}"
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
166 log.error(msg)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
167
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
168 raise exceptions.DatabaseError(msg)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
169
4003
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
170 async def create_db(self, engine: AsyncEngine, db_config: dict) -> None:
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
171 """Create a new database
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
172
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
173 The database is generated from SQLAlchemy model, then stamped by Alembic
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
174 """
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
175 # the dir may not exist if it's not the XDG recommended one
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
176 db_config["path"].parent.mkdir(0o700, True, True)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
177 async with engine.begin() as conn:
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
178 await conn.run_sync(Base.metadata.create_all)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
179
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
180 log.debug("stamping the database")
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
181 await self.migrate_apply("stamp", "head")
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
182 log.debug("stamping done")
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
183
4003
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
184 def _check_db_is_up_to_date(self, conn: Connection) -> bool:
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
185 al_ini_path = migration_path / "alembic.ini"
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
186 al_cfg = al_config.Config(al_ini_path)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
187 directory = al_script.ScriptDirectory.from_config(al_cfg)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
188 context = al_migration.MigrationContext.configure(conn)
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
189 return set(context.get_current_heads()) == set(directory.get_heads())
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
190
4003
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
191 def _sqlite_set_journal_mode_wal(self, conn: Connection) -> None:
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
192 """Check if journal mode is WAL, and set it if necesssary"""
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
193 result = conn.execute(text("PRAGMA journal_mode"))
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
194 if result.scalar() != "wal":
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
195 log.info("WAL mode not activated, activating it")
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
196 conn.execute(text("PRAGMA journal_mode=WAL"))
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
197
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
198 async def check_and_update_db(self, engine: AsyncEngine, db_config: dict) -> None:
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
199 """Check that database is up-to-date, and update if necessary"""
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
200 async with engine.connect() as conn:
4003
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
201 up_to_date = await conn.run_sync(self._check_db_is_up_to_date)
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
202 if up_to_date:
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
203 log.debug("Database is up-to-date")
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
204 else:
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
205 log.info("Database needs to be updated")
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
206 log.info("updating…")
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
207 await self.migrate_apply("upgrade", "head", log_output=True)
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
208 log.info("Database is now up-to-date")
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
209
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
210 @aio
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
211 async def initialise(self) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
212 log.info(_("Connecting database"))
3583
16ade4ad63f3 core (memory/sqla_mapping): fix some technical debt:
Goffi <goffi@goffi.org>
parents: 3582
diff changeset
213
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
214 db_config = sqla_config.get_db_config()
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
215 engine = create_async_engine(
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
216 db_config["url"],
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
217 future=True,
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4212
diff changeset
218 json_serializer=lambda obj: json.dumps(obj, ensure_ascii=False),
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
219 )
3583
16ade4ad63f3 core (memory/sqla_mapping): fix some technical debt:
Goffi <goffi@goffi.org>
parents: 3582
diff changeset
220
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
221 new_base = not db_config["path"].exists()
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
222 if new_base:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
223 log.info(_("The database is new, creating the tables"))
4003
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
224 await self.create_db(engine, db_config)
3582
71516731d0aa core (memory/sqla): database migration using Alembic:
Goffi <goffi@goffi.org>
parents: 3537
diff changeset
225 else:
4003
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
226 await self.check_and_update_db(engine, db_config)
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
227
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
228 async with engine.connect() as conn:
1a77e1f866f9 core (memory/sqla): activate Write-Ahead Logging:
Goffi <goffi@goffi.org>
parents: 3893
diff changeset
229 await conn.run_sync(self._sqlite_set_journal_mode_wal)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
230
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
231 self.session = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)
3583
16ade4ad63f3 core (memory/sqla_mapping): fix some technical debt:
Goffi <goffi@goffi.org>
parents: 3582
diff changeset
232
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
233 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
234 result = await session.execute(select(Profile))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
235 for p in result.scalars():
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
236 self.profiles[p.name] = p.id
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
237 result = await session.execute(select(Component))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
238 for c in result.scalars():
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
239 self.components[c.profile_id] = c.entry_point
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
240
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
241 self.initialized.callback(None)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
242
3596
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
243 ## Generic
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
244
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
245 @aio
3798
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
246 async def get(
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
247 self,
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
248 client: SatXMPPEntity,
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
249 db_cls: DeclarativeMeta,
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
250 db_id_col: Mapped,
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
251 id_value: Any,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
252 joined_loads=None,
3798
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
253 ) -> Optional[DeclarativeMeta]:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
254 stmt = select(db_cls).where(db_id_col == id_value)
3798
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
255 if client is not None:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
256 stmt = stmt.filter_by(profile_id=self.profiles[client.profile])
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
257 if joined_loads is not None:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
258 for joined_load in joined_loads:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
259 stmt = stmt.options(joinedload(joined_load))
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
260 async with self.session() as session:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
261 result = await session.execute(stmt)
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
262 if joined_loads is not None:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
263 result = result.unique()
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
264 return result.scalar_one_or_none()
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
265
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
266 @aio
3596
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
267 async def add(self, db_obj: DeclarativeMeta) -> None:
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
268 """Add an object to database"""
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
269 async with self.session() as session:
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
270 async with session.begin():
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
271 session.add(db_obj)
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
272
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
273 @aio
3798
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
274 async def delete(
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
275 self,
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
276 db_obj: Union[DeclarativeMeta, List[DeclarativeMeta]],
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
277 session_add: Optional[List[DeclarativeMeta]] = None,
3798
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
278 ) -> None:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
279 """Delete an object from database
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
280
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
281 @param db_obj: object to delete or list of objects to delete
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
282 @param session_add: other objects to add to session.
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
283 This is useful when parents of deleted objects needs to be updated too, or if
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
284 other objects needs to be updated in the same transaction.
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
285 """
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
286 if not db_obj:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
287 return
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
288 if not isinstance(db_obj, list):
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
289 db_obj = [db_obj]
3596
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
290 async with self.session() as session:
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
291 async with session.begin():
3798
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
292 if session_add is not None:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
293 for obj in session_add:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
294 session.add(obj)
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
295 for obj in db_obj:
b5013bada4b6 core (memory/sqla): generic `get` + `session_add` in `delete`:
Goffi <goffi@goffi.org>
parents: 3797
diff changeset
296 await session.delete(obj)
3596
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
297 await session.commit()
2d97c695af05 core (memory/sqla): generic methods to add and delete ORM objects directly
Goffi <goffi@goffi.org>
parents: 3595
diff changeset
298
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
299 ## Profiles
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
300
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
301 def get_profiles_list(self) -> List[str]:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
302 """ "Return list of all registered profiles"""
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
303 return list(self.profiles.keys())
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
304
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
305 def has_profile(self, profile_name: str) -> bool:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
306 """return True if profile_name exists
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
307
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
308 @param profile_name: name of the profile to check
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
309 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
310 return profile_name in self.profiles
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
311
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
312 def profile_is_component(self, profile_name: str) -> bool:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
313 try:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
314 return self.profiles[profile_name] in self.components
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
315 except KeyError:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
316 raise exceptions.NotFound("the requested profile doesn't exists")
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
317
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
318 def get_entry_point(self, profile_name: str) -> str:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
319 try:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
320 return self.components[self.profiles[profile_name]]
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
321 except KeyError:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
322 raise exceptions.NotFound(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
323 "the requested profile doesn't exists or is not a component"
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
324 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
325
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
326 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
327 async def create_profile(self, name: str, component_ep: Optional[str] = None) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
328 """Create a new profile
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
329
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
330 @param name: name of the profile
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
331 @param component: if not None, must point to a component entry point
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
332 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
333 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
334 profile = Profile(name=name)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
335 async with session.begin():
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
336 session.add(profile)
3638
257135d5c5c2 core (memory/sqla): fix key/value inversion in self.profiles
Goffi <goffi@goffi.org>
parents: 3621
diff changeset
337 self.profiles[profile.name] = profile.id
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
338 if component_ep is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
339 async with session.begin():
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
340 component = Component(profile=profile, entry_point=component_ep)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
341 session.add(component)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
342 self.components[profile.id] = component_ep
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
343 return profile
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
344
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
345 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
346 async def delete_profile(self, name: str) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
347 """Delete profile
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
348
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
349 @param name: name of the profile
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
350 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
351 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
352 result = await session.execute(select(Profile).where(Profile.name == name))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
353 profile = result.scalar()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
354 await session.delete(profile)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
355 await session.commit()
3638
257135d5c5c2 core (memory/sqla): fix key/value inversion in self.profiles
Goffi <goffi@goffi.org>
parents: 3621
diff changeset
356 del self.profiles[profile.name]
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
357 if profile.id in self.components:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
358 del self.components[profile.id]
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
359 log.info(_("Profile {name!r} deleted").format(name=name))
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
360
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
361 ## Params
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
362
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
363 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
364 async def load_gen_params(self, params_gen: dict) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
365 """Load general parameters
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
366
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
367 @param params_gen: dictionary to fill
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
368 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
369 log.debug(_("loading general parameters from database"))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
370 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
371 result = await session.execute(select(ParamGen))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
372 for p in result.scalars():
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
373 params_gen[(p.category, p.name)] = p.value
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
374
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
375 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
376 async def load_ind_params(self, params_ind: dict, profile: str) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
377 """Load individual parameters
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
378
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
379 @param params_ind: dictionary to fill
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
380 @param profile: a profile which *must* exist
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
381 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
382 log.debug(_("loading individual parameters from database"))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
383 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
384 result = await session.execute(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
385 select(ParamInd).where(ParamInd.profile_id == self.profiles[profile])
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
386 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
387 for p in result.scalars():
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
388 params_ind[(p.category, p.name)] = p.value
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
389
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
390 @aio
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
391 async def get_ind_param(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
392 self, category: str, name: str, profile: str
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
393 ) -> Optional[str]:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
394 """Ask database for the value of one specific individual parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
395
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
396 @param category: category of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
397 @param name: name of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
398 @param profile: %(doc_profile)s
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
399 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
400 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
401 result = await session.execute(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
402 select(ParamInd.value).filter_by(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
403 category=category, name=name, profile_id=self.profiles[profile]
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
404 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
405 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
406 return result.scalar_one_or_none()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
407
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
408 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
409 async def get_ind_param_values(self, category: str, name: str) -> Dict[str, str]:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
410 """Ask database for the individual values of a parameter for all profiles
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
411
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
412 @param category: category of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
413 @param name: name of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
414 @return dict: profile => value map
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
415 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
416 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
417 result = await session.execute(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
418 select(ParamInd)
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
419 .filter_by(category=category, name=name)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
420 .options(subqueryload(ParamInd.profile))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
421 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
422 return {param.profile.name: param.value for param in result.scalars()}
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
423
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
424 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
425 async def set_gen_param(self, category: str, name: str, value: Optional[str]) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
426 """Save the general parameters in database
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
427
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
428 @param category: category of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
429 @param name: name of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
430 @param value: value to set
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
431 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
432 async with self.session() as session:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
433 stmt = (
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
434 insert(ParamGen)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
435 .values(category=category, name=name, value=value)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
436 .on_conflict_do_update(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
437 index_elements=(ParamGen.category, ParamGen.name),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
438 set_={ParamGen.value: value},
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
439 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
440 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
441 await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
442 await session.commit()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
443
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
444 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
445 async def set_ind_param(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
446 self, category: str, name: str, value: Optional[str], profile: str
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
447 ) -> None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
448 """Save the individual parameters in database
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
449
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
450 @param category: category of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
451 @param name: name of the parameter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
452 @param value: value to set
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
453 @param profile: a profile which *must* exist
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
454 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
455 async with self.session() as session:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
456 stmt = (
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
457 insert(ParamInd)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
458 .values(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
459 category=category,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
460 name=name,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
461 profile_id=self.profiles[profile],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
462 value=value,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
463 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
464 .on_conflict_do_update(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
465 index_elements=(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
466 ParamInd.category,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
467 ParamInd.name,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
468 ParamInd.profile_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
469 ),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
470 set_={ParamInd.value: value},
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
471 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
472 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
473 await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
474 await session.commit()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
475
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
476 def _jid_filter(self, jid_: jid.JID, dest: bool = False):
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
477 """Generate condition to filter on a JID, using relevant columns
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
478
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
479 @param dest: True if it's the destinee JID, otherwise it's the source one
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
480 @param jid_: JID to filter by
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
481 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
482 if jid_.resource:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
483 if dest:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
484 return and_(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
485 History.dest == jid_.userhost(), History.dest_res == jid_.resource
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
486 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
487 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
488 return and_(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
489 History.source == jid_.userhost(), History.source_res == jid_.resource
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
490 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
491 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
492 if dest:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
493 return History.dest == jid_.userhost()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
494 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
495 return History.source == jid_.userhost()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
496
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
497 @aio
4366
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
498 async def get_history_from_xmpp_id(
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
499 self, client: SatXMPPEntity, message_id: str, message_type: str|None
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
500 ) -> History | None:
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
501 """Retrieves history row that match a specific message ID.
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
502
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
503 The retrieval criteria vary based on the message type.
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
504
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
505 @param message_type: The type of the message (one of C.MESS_TYPE_*)
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
506 @param message_id: the ID of the message, XEP-0359's stanza-id is used for
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
507 groupchat, origin-id from the same XEP otherwise.
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
508 @return: History instance with messages, subjects and threads, if any found, None
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
509 otherwise.
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
510 """
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
511 profile_id = self.profiles[client.profile]
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
512 async with self.session() as session:
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
513 if message_type == C.MESS_TYPE_GROUPCHAT:
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
514 query = select(History).where(
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
515 History.profile_id == profile_id, History.stanza_id == message_id
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
516 )
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
517 else:
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
518 query = select(History).where(
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
519 History.profile_id == profile_id, History.origin_id == message_id
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
520 )
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
521
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
522 query = (
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
523 query
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
524 .outerjoin(History.messages)
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
525 .outerjoin(History.subjects)
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
526 .outerjoin(History.thread)
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
527 .options(
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
528 contains_eager(History.messages),
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
529 contains_eager(History.subjects),
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
530 contains_eager(History.thread),
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
531 )
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
532 )
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
533
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
534 result = await session.execute(query)
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
535 history = result.scalars().first()
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
536
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
537 return history
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
538
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
539
1ef32316a55e plugin XEP-0444, storage: move `get_history_from_xmpp_id` to storage as it is generally useful.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
540 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
541 async def history_get(
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
542 self,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
543 from_jid: Optional[jid.JID],
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
544 to_jid: Optional[jid.JID],
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
545 limit: Optional[int] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
546 between: bool = True,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
547 filters: Optional[Dict[str, str]] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
548 profile: Optional[str] = None,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
549 ) -> List[Tuple[str, int, str, str, Dict[str, str], Dict[str, str], str, str, str]]:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
550 """Retrieve messages in history
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
551
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
552 @param from_jid: source JID (full, or bare for catchall)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
553 @param to_jid: dest JID (full, or bare for catchall)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
554 @param limit: maximum number of messages to get:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
555 - 0 for no message (returns the empty list)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
556 - None for unlimited
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
557 @param between: confound source and dest (ignore the direction)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
558 @param filters: pattern to filter the history results
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
559 @return: list of messages as in [message_new], minus the profile which is already
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
560 known.
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
561 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
562 # we have to set a default value to profile because it's last argument
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
563 # and thus follow other keyword arguments with default values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
564 # but None should not be used for it
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
565 assert profile is not None
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
566 if limit == 0:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
567 return []
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
568 if filters is None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
569 filters = {}
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
570
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
571 stmt = (
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
572 select(History)
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
573 .filter_by(profile_id=self.profiles[profile])
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
574 .outerjoin(History.messages)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
575 .outerjoin(History.subjects)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
576 .outerjoin(History.thread)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
577 .options(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
578 contains_eager(History.messages),
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
579 contains_eager(History.subjects),
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
580 contains_eager(History.thread),
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
581 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
582 .order_by(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
583 # timestamp may be identical for 2 close messages (specially when delay is
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
584 # used) that's why we order ties by received_timestamp. We'll reverse the
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
585 # order when returning the result. We use DESC here so LIMIT keep the last
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
586 # messages
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
587 History.timestamp.desc(),
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
588 History.received_timestamp.desc(),
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
589 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
590 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
591
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
592 if not from_jid and not to_jid:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
593 # no jid specified, we want all one2one communications
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
594 pass
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
595 elif between:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
596 if not from_jid or not to_jid:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
597 # we only have one jid specified, we check all messages
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
598 # from or to this jid
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
599 jid_ = from_jid or to_jid
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
600 stmt = stmt.where(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
601 or_(self._jid_filter(jid_), self._jid_filter(jid_, dest=True))
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
602 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
603 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
604 # we have 2 jids specified, we check all communications between
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
605 # those 2 jids
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
606 stmt = stmt.where(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
607 or_(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
608 and_(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
609 self._jid_filter(from_jid),
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
610 self._jid_filter(to_jid, dest=True),
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
611 ),
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
612 and_(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
613 self._jid_filter(to_jid),
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
614 self._jid_filter(from_jid, dest=True),
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
615 ),
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
616 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
617 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
618 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
619 # we want one communication in specific direction (from somebody or
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
620 # to somebody).
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
621 if from_jid is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
622 stmt = stmt.where(self._jid_filter(from_jid))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
623 if to_jid is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
624 stmt = stmt.where(self._jid_filter(to_jid, dest=True))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
625
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
626 if filters:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
627 if "timestamp_start" in filters:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
628 stmt = stmt.where(History.timestamp >= float(filters["timestamp_start"]))
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
629 if "before_uid" in filters:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
630 # orignially this query was using SQLITE's rowid. This has been changed
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
631 # to use coalesce(received_timestamp, timestamp) to be SQL engine independant
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
632 stmt = stmt.where(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
633 coalesce(History.received_timestamp, History.timestamp)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
634 < (
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
635 select(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
636 coalesce(History.received_timestamp, History.timestamp)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
637 ).filter_by(uid=filters["before_uid"])
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
638 ).scalar_subquery()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
639 )
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
640 if "body" in filters:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
641 # TODO: use REGEXP (function to be defined) instead of GLOB: https://www.sqlite.org/lang_expr.html
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
642 stmt = stmt.where(Message.message.like(f"%{filters['body']}%"))
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
643 if "search" in filters:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
644 search_term = f"%{filters['search']}%"
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
645 stmt = stmt.where(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
646 or_(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
647 Message.message.like(search_term),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
648 History.source_res.like(search_term),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
649 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
650 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
651 if "types" in filters:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
652 types = filters["types"].split()
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
653 stmt = stmt.where(History.type.in_(types))
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
654 if "not_types" in filters:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
655 types = filters["not_types"].split()
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
656 stmt = stmt.where(History.type.not_in(types))
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
657 if "last_stanza_id" in filters:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
658 # this request get the last message with a "stanza_id" that we
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
659 # have in history. This is mainly used to retrieve messages sent
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
660 # while we were offline, using MAM (XEP-0313).
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
661 if filters["last_stanza_id"] is not True or limit != 1:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
662 raise ValueError("Unexpected values for last_stanza_id filter")
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
663 stmt = stmt.where(History.stanza_id.is_not(None))
4160
6a0066ea5c97 core (memory/sqla): add `id` filter in `history_get`
Goffi <goffi@goffi.org>
parents: 4130
diff changeset
664 if "id" in filters:
6a0066ea5c97 core (memory/sqla): add `id` filter in `history_get`
Goffi <goffi@goffi.org>
parents: 4130
diff changeset
665 stmt = stmt.where(History.uid == filters["id"])
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
666 if "origin_id" in filters:
3797
cc653b2685f0 core (memory/sqla), plugin XEP-0359: always add `origin-id`, and store:
Goffi <goffi@goffi.org>
parents: 3754
diff changeset
667 stmt = stmt.where(History.origin_id == filters["origin_id"])
4367
b93f95efe329 storage: Add a `thread_id` filter to `history_get`:
Goffi <goffi@goffi.org>
parents: 4366
diff changeset
668 if "thread_id" in filters:
b93f95efe329 storage: Add a `thread_id` filter to `history_get`:
Goffi <goffi@goffi.org>
parents: 4366
diff changeset
669 stmt = stmt.where(Thread.thread_id == filters["thread_id"])
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
670
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
671 if limit is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
672 stmt = stmt.limit(limit)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
673
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
674 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
675 result = await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
676
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
677 result = result.scalars().unique().all()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
678 result.reverse()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
679 return [h.as_tuple() for h in result]
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
680
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
681 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
682 async def add_to_history(self, data: dict, profile: str) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
683 """Store a new message in history
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
684
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
685 @param data: message data as build by SatMessageProtocol.onMessage
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
686 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
687 extra = {k: v for k, v in data["extra"].items() if k not in NOT_IN_EXTRA}
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
688 messages = [
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
689 Message(message=mess, language=lang) for lang, mess in data["message"].items()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
690 ]
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
691 subjects = [
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
692 Subject(subject=mess, language=lang) for lang, mess in data["subject"].items()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
693 ]
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
694 if "thread" in data["extra"]:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
695 thread = Thread(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
696 thread_id=data["extra"]["thread"],
4367
b93f95efe329 storage: Add a `thread_id` filter to `history_get`:
Goffi <goffi@goffi.org>
parents: 4366
diff changeset
697 parent_id=data["extra"].get("thread_parent"),
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
698 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
699 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
700 thread = None
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
701 try:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
702 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
703 async with session.begin():
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
704 session.add(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
705 History(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
706 uid=data["uid"],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
707 origin_id=data["extra"].get("origin_id"),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
708 stanza_id=data["extra"].get("stanza_id"),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
709 update_uid=data["extra"].get("update_uid"),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
710 profile_id=self.profiles[profile],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
711 source_jid=data["from"],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
712 dest_jid=data["to"],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
713 timestamp=data["timestamp"],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
714 received_timestamp=data.get("received_timestamp"),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
715 type=data["type"],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
716 extra=extra,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
717 messages=messages,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
718 subjects=subjects,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
719 thread=thread,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
720 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
721 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
722 except IntegrityError as e:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
723 if "unique" in str(e.orig).lower():
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
724 log.debug(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
725 f"message {data['uid']!r} is already in history, not storing it again"
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
726 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
727 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
728 log.error(f"Can't store message {data['uid']!r} in history: {e}")
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
729 except Exception as e:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
730 log.critical(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
731 f"Can't store message, unexpected exception (uid: {data['uid']}): {e}"
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
732 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
733
4368
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
734 @aio
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
735 async def add_thread(
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
736 self,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
737 message_uid: str,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
738 thread_id: str,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
739 parent_id: str|None,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
740 is_retroactive: bool,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
741 ) -> None:
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
742 """Add a thread to a message.
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
743
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
744 @param message_uid: Internal ID of the message (History.uid) to which the thread
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
745 is added.
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
746 @param thread_id: The thread ID to set.
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
747 @param parent_id: The parent message ID in the thread.
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
748 @param is_retroactive: Whether the thread ID was added after the message was sent.
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
749 Is is used when we want to relate a parent message to a new thread, when the
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
750 parent message didn't have a thread ID initially.
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
751 """
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
752 async with self.session() as session:
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
753 thread = Thread(
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
754 thread_id=thread_id,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
755 parent_id=parent_id,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
756 is_retroactive=is_retroactive,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
757 history_uid=message_uid,
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
758 )
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
759 session.add(thread)
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
760 await session.commit()
2bdf0c16d852 storage: Add a `add_thread` method:
Goffi <goffi@goffi.org>
parents: 4367
diff changeset
761
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
762 ## Private values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
763
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
764 def _get_private_class(self, binary, profile):
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
765 """Get ORM class to use for private values"""
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
766 if profile is None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
767 return PrivateGenBin if binary else PrivateGen
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
768 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
769 return PrivateIndBin if binary else PrivateInd
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
770
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
771 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
772 async def get_privates(
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
773 self,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
774 namespace: str,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
775 keys: Optional[Iterable[str]] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
776 binary: bool = False,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
777 profile: Optional[str] = None,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
778 ) -> Dict[str, Any]:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
779 """Get private value(s) from databases
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
780
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
781 @param namespace: namespace of the values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
782 @param keys: keys of the values to get None to get all keys/values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
783 @param binary: True to deserialise binary values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
784 @param profile: profile to use for individual values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
785 None to use general values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
786 @return: gotten keys/values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
787 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
788 if keys is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
789 keys = list(keys)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
790 log.debug(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
791 f"getting {'general' if profile is None else 'individual'}"
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
792 f"{' binary' if binary else ''} private values from database for namespace "
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
793 f"{namespace}{f' with keys {keys!r}' if keys is not None else ''}"
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
794 )
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
795 cls = self._get_private_class(binary, profile)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
796 stmt = select(cls).filter_by(namespace=namespace)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
797 if keys:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
798 stmt = stmt.where(cls.key.in_(list(keys)))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
799 if profile is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
800 stmt = stmt.filter_by(profile_id=self.profiles[profile])
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
801 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
802 result = await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
803 return {p.key: p.value for p in result.scalars()}
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
804
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
805 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
806 async def set_private_value(
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
807 self,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
808 namespace: str,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
809 key: str,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
810 value: Any,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
811 binary: bool = False,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
812 profile: Optional[str] = None,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
813 ) -> None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
814 """Set a private value in database
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
815
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
816 @param namespace: namespace of the values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
817 @param key: key of the value to set
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
818 @param value: value to set
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
819 @param binary: True if it's a binary values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
820 binary values need to be serialised, used for everything but strings
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
821 @param profile: profile to use for individual value
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
822 if None, it's a general value
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
823 """
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
824 cls = self._get_private_class(binary, profile)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
825
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
826 values = {"namespace": namespace, "key": key, "value": value}
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
827 index_elements = [cls.namespace, cls.key]
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
828
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
829 if profile is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
830 values["profile_id"] = self.profiles[profile]
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
831 index_elements.append(cls.profile_id)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
832
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
833 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
834 await session.execute(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
835 insert(cls)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
836 .values(**values)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
837 .on_conflict_do_update(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
838 index_elements=index_elements, set_={cls.value: value}
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
839 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
840 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
841 await session.commit()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
842
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
843 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
844 async def del_private_value(
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
845 self,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
846 namespace: str,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
847 key: str,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
848 binary: bool = False,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
849 profile: Optional[str] = None,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
850 ) -> None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
851 """Delete private value from database
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
852
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
853 @param category: category of the privateeter
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
854 @param key: key of the private value
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
855 @param binary: True if it's a binary values
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
856 @param profile: profile to use for individual value
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
857 if None, it's a general value
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
858 """
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
859 cls = self._get_private_class(binary, profile)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
860
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
861 stmt = delete(cls).filter_by(namespace=namespace, key=key)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
862
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
863 if profile is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
864 stmt = stmt.filter_by(profile_id=self.profiles[profile])
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
865
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
866 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
867 await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
868 await session.commit()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
869
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
870 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
871 async def del_private_namespace(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
872 self, namespace: str, binary: bool = False, profile: Optional[str] = None
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
873 ) -> None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
874 """Delete all data from a private namespace
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
875
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
876 Be really cautious when you use this method, as all data with given namespace are
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
877 removed.
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
878 Params are the same as for del_private_value
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
879 """
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
880 cls = self._get_private_class(binary, profile)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
881
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
882 stmt = delete(cls).filter_by(namespace=namespace)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
883
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
884 if profile is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
885 stmt = stmt.filter_by(profile_id=self.profiles[profile])
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
886
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
887 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
888 await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
889 await session.commit()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
890
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
891 ## Files
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
892
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
893 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
894 async def get_files(
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
895 self,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
896 client: Optional[SatXMPPEntity],
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
897 file_id: Optional[str] = None,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
898 version: Optional[str] = "",
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
899 parent: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
900 type_: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
901 file_hash: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
902 hash_algo: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
903 name: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
904 namespace: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
905 mime_type: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
906 public_id: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
907 owner: Optional[jid.JID] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
908 access: Optional[dict] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
909 projection: Optional[List[str]] = None,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
910 unique: bool = False,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
911 ) -> List[dict]:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
912 """Retrieve files with with given filters
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
913
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
914 @param file_id: id of the file
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
915 None to ignore
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
916 @param version: version of the file
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
917 None to ignore
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
918 empty string to look for current version
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
919 @param parent: id of the directory containing the files
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
920 None to ignore
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
921 empty string to look for root files/directories
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
922 @param projection: name of columns to retrieve
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
923 None to retrieve all
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
924 @param unique: if True will remove duplicates
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
925 other params are the same as for [set_file]
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
926 @return: files corresponding to filters
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
927 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
928 if projection is None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
929 projection = [
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
930 "id",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
931 "version",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
932 "parent",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
933 "type",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
934 "file_hash",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
935 "hash_algo",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
936 "name",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
937 "size",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
938 "namespace",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
939 "media_type",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
940 "media_subtype",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
941 "public_id",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
942 "created",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
943 "modified",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
944 "owner",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
945 "access",
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
946 "extra",
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
947 ]
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
948
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
949 stmt = select(*[getattr(File, f) for f in projection])
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
950
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
951 if unique:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
952 stmt = stmt.distinct()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
953
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
954 if client is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
955 stmt = stmt.filter_by(profile_id=self.profiles[client.profile])
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
956 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
957 if public_id is None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
958 raise exceptions.InternalError(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
959 "client can only be omitted when public_id is set"
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
960 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
961 if file_id is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
962 stmt = stmt.filter_by(id=file_id)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
963 if version is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
964 stmt = stmt.filter_by(version=version)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
965 if parent is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
966 stmt = stmt.filter_by(parent=parent)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
967 if type_ is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
968 stmt = stmt.filter_by(type=type_)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
969 if file_hash is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
970 stmt = stmt.filter_by(file_hash=file_hash)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
971 if hash_algo is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
972 stmt = stmt.filter_by(hash_algo=hash_algo)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
973 if name is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
974 stmt = stmt.filter_by(name=name)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
975 if namespace is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
976 stmt = stmt.filter_by(namespace=namespace)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
977 if mime_type is not None:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
978 if "/" in mime_type:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
979 media_type, media_subtype = mime_type.split("/", 1)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
980 stmt = stmt.filter_by(media_type=media_type, media_subtype=media_subtype)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
981 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
982 stmt = stmt.filter_by(media_type=mime_type)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
983 if public_id is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
984 stmt = stmt.filter_by(public_id=public_id)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
985 if owner is not None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
986 stmt = stmt.filter_by(owner=owner)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
987 if access is not None:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
988 raise NotImplementedError("Access check is not implemented yet")
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
989 # a JSON comparison is needed here
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
990
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
991 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
992 result = await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
993
4092
74c66c0d93f3 core (memory/sqla): fix row to dict conversion in `get_files`
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
994 return [r._asdict() for r in result]
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
995
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
996 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
997 async def set_file(
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
998 self,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
999 client: SatXMPPEntity,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1000 name: str,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1001 file_id: str,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1002 version: str = "",
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1003 parent: str = "",
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1004 type_: str = C.FILE_TYPE_FILE,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1005 file_hash: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1006 hash_algo: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1007 size: int = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1008 namespace: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1009 mime_type: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1010 public_id: Optional[str] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1011 created: Optional[float] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1012 modified: Optional[float] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1013 owner: Optional[jid.JID] = None,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1014 access: Optional[dict] = None,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1015 extra: Optional[dict] = None,
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1016 ) -> None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1017 """Set a file metadata
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1018
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1019 @param client: client owning the file
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1020 @param name: name of the file (must not contain "/")
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1021 @param file_id: unique id of the file
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1022 @param version: version of this file
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1023 @param parent: id of the directory containing this file
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1024 Empty string if it is a root file/directory
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1025 @param type_: one of:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1026 - file
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1027 - directory
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1028 @param file_hash: unique hash of the payload
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1029 @param hash_algo: algorithm used for hashing the file (usually sha-256)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1030 @param size: size in bytes
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1031 @param namespace: identifier (human readable is better) to group files
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1032 for instance, namespace could be used to group files in a specific photo album
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1033 @param mime_type: media type of the file, or None if not known/guessed
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1034 @param public_id: ID used to server the file publicly via HTTP
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1035 @param created: UNIX time of creation
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1036 @param modified: UNIX time of last modification, or None to use created date
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1037 @param owner: jid of the owner of the file (mainly useful for component)
3621
9e1a993ad1bf core (memory/sqla): minor docstring line lenght fix
Goffi <goffi@goffi.org>
parents: 3596
diff changeset
1038 @param access: serialisable dictionary with access rules. See [memory.memory] for
9e1a993ad1bf core (memory/sqla): minor docstring line lenght fix
Goffi <goffi@goffi.org>
parents: 3596
diff changeset
1039 details
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1040 @param extra: serialisable dictionary of any extra data
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1041 will be encoded to json in database
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1042 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1043 if mime_type is None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1044 media_type = media_subtype = None
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1045 elif "/" in mime_type:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1046 media_type, media_subtype = mime_type.split("/", 1)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1047 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1048 media_type, media_subtype = mime_type, None
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1049
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1050 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1051 async with session.begin():
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1052 session.add(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1053 File(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1054 id=file_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1055 version=version.strip(),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1056 parent=parent,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1057 type=type_,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1058 file_hash=file_hash,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1059 hash_algo=hash_algo,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1060 name=name,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1061 size=size,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1062 namespace=namespace,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1063 media_type=media_type,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1064 media_subtype=media_subtype,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1065 public_id=public_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1066 created=time.time() if created is None else created,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1067 modified=modified,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1068 owner=owner,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1069 access=access,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1070 extra=extra,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1071 profile_id=self.profiles[client.profile],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1072 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1073 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1074
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1075 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1076 async def file_get_used_space(self, client: SatXMPPEntity, owner: jid.JID) -> int:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1077 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1078 result = await session.execute(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1079 select(sum_(File.size)).filter_by(
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1080 owner=owner,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1081 type=C.FILE_TYPE_FILE,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1082 profile_id=self.profiles[client.profile],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1083 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1084 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1085 return result.scalar_one_or_none() or 0
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1086
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1087 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1088 async def file_delete(self, file_id: str) -> None:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1089 """Delete file metadata from the database
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1090
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1091 @param file_id: id of the file to delete
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1092 NOTE: file itself must still be removed, this method only handle metadata in
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1093 database
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1094 """
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1095 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1096 await session.execute(delete(File).filter_by(id=file_id))
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1097 await session.commit()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1098
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1099 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1100 async def file_update(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1101 self, file_id: str, column: str, update_cb: Callable[[dict], None]
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1102 ) -> None:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1103 """Update a column value using a method to avoid race conditions
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1104
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1105 the older value will be retrieved from database, then update_cb will be applied to
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1106 update it, and file will be updated checking that older value has not been changed
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1107 meanwhile by an other user. If it has changed, it tries again a couple of times
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1108 before failing
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1109 @param column: column name (only "access" or "extra" are allowed)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1110 @param update_cb: method to update the value of the colum
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1111 the method will take older value as argument, and must update it in place
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1112 update_cb must not care about serialization,
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1113 it get the deserialized data (i.e. a Python object) directly
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1114 @raise exceptions.NotFound: there is not file with this id
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1115 """
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1116 if column not in ("access", "extra"):
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1117 raise exceptions.InternalError("bad column name")
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1118 orm_col = getattr(File, column)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1119
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1120 for i in range(5):
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1121 async with self.session() as session:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1122 try:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1123 value = (
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1124 await session.execute(select(orm_col).filter_by(id=file_id))
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1125 ).scalar_one()
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1126 except NoResultFound:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1127 raise exceptions.NotFound
3673
bd13391ee29e core (memory/sqla): fix `fileUpdate`
Goffi <goffi@goffi.org>
parents: 3665
diff changeset
1128 old_value = copy.deepcopy(value)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1129 update_cb(value)
3673
bd13391ee29e core (memory/sqla): fix `fileUpdate`
Goffi <goffi@goffi.org>
parents: 3665
diff changeset
1130 stmt = update(File).filter_by(id=file_id).values({column: value})
bd13391ee29e core (memory/sqla): fix `fileUpdate`
Goffi <goffi@goffi.org>
parents: 3665
diff changeset
1131 if not old_value:
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1132 # because JsonDefaultDict convert NULL to an empty dict, we have to
3673
bd13391ee29e core (memory/sqla): fix `fileUpdate`
Goffi <goffi@goffi.org>
parents: 3665
diff changeset
1133 # test both for empty dict and None when we have an empty dict
bd13391ee29e core (memory/sqla): fix `fileUpdate`
Goffi <goffi@goffi.org>
parents: 3665
diff changeset
1134 stmt = stmt.where((orm_col == None) | (orm_col == old_value))
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1135 else:
3673
bd13391ee29e core (memory/sqla): fix `fileUpdate`
Goffi <goffi@goffi.org>
parents: 3665
diff changeset
1136 stmt = stmt.where(orm_col == old_value)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1137 result = await session.execute(stmt)
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1138 await session.commit()
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1139
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1140 if result.rowcount == 1:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1141 break
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1142
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1143 log.warning(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1144 _(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1145 "table not updated, probably due to race condition, trying again "
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1146 "({tries})"
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1147 ).format(tries=i + 1)
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1148 )
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1149
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1150 else:
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1151 raise exceptions.DatabaseError(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1152 _("Can't update file {file_id} due to race condition").format(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1153 file_id=file_id
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1154 )
3537
f9a5b810f14d core (memory/storage): backend storage is now based on SQLAlchemy
Goffi <goffi@goffi.org>
parents:
diff changeset
1155 )
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1156
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1157 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1158 async def get_pubsub_node(
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1159 self,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1160 client: SatXMPPEntity,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1161 service: jid.JID,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1162 name: str,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1163 with_items: bool = False,
3744
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1164 with_subscriptions: bool = False,
3862
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1165 create: bool = False,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1166 create_kwargs: Optional[dict] = None,
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1167 ) -> Optional[PubsubNode]:
3862
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1168 """Retrieve a PubsubNode from DB
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1169
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1170 @param service: service hosting the node
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1171 @param name: node's name
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1172 @param with_items: retrieve items in the same query
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1173 @param with_subscriptions: retrieve subscriptions in the same query
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1174 @param create: if the node doesn't exist in DB, create it
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1175 @param create_kwargs: keyword arguments to use with ``set_pubsub_node`` if the node
3862
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1176 needs to be created.
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1177 """
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1178 async with self.session() as session:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1179 stmt = select(PubsubNode).filter_by(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1180 service=service,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1181 name=name,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1182 profile_id=self.profiles[client.profile],
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1183 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1184 if with_items:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1185 stmt = stmt.options(joinedload(PubsubNode.items))
3744
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1186 if with_subscriptions:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1187 stmt = stmt.options(joinedload(PubsubNode.subscriptions))
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1188 result = await session.execute(stmt)
3862
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1189 ret = result.unique().scalar_one_or_none()
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1190 if ret is None and create:
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1191 # we auto-create the node
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1192 if create_kwargs is None:
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1193 create_kwargs = {}
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1194 try:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1195 return await as_future(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1196 self.set_pubsub_node(client, service, name, **create_kwargs)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1197 )
3862
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1198 except IntegrityError as e:
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1199 if "unique" in str(e.orig).lower():
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1200 # the node may already exist, if it has been created just after
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1201 # get_pubsub_node above
3862
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1202 log.debug("ignoring UNIQUE constraint error")
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1203 cached_node = await as_future(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1204 self.get_pubsub_node(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1205 client,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1206 service,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1207 name,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1208 with_items=with_items,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1209 with_subscriptions=with_subscriptions,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1210 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1211 )
3862
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1212 else:
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1213 raise e
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1214 else:
100dd30244c6 core (memory/sqla): add argument to `getPubsubNode` to auto-create a node:
Goffi <goffi@goffi.org>
parents: 3813
diff changeset
1215 return ret
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1216
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1217 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1218 async def set_pubsub_node(
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1219 self,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1220 client: SatXMPPEntity,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1221 service: jid.JID,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1222 name: str,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1223 analyser: Optional[str] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1224 type_: Optional[str] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1225 subtype: Optional[str] = None,
3744
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1226 subscribed: bool = False,
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1227 ) -> PubsubNode:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1228 node = PubsubNode(
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1229 profile_id=self.profiles[client.profile],
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1230 service=service,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1231 name=name,
3744
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1232 subscribed=subscribed,
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1233 analyser=analyser,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1234 type_=type_,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1235 subtype=subtype,
3744
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1236 subscriptions=[],
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1237 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1238 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1239 async with session.begin():
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1240 session.add(node)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1241 return node
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1242
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1243 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1244 async def update_pubsub_node_sync_state(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1245 self, node: PubsubNode, state: SyncState
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1246 ) -> None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1247 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1248 async with session.begin():
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1249 await session.execute(
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1250 update(PubsubNode)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1251 .filter_by(id=node.id)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1252 .values(
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1253 sync_state=state,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1254 sync_state_updated=time.time(),
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1255 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1256 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1257
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1258 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1259 async def delete_pubsub_node(
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1260 self,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1261 profiles: Optional[List[str]],
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1262 services: Optional[List[jid.JID]],
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1263 names: Optional[List[str]],
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1264 ) -> None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1265 """Delete items cached for a node
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1266
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1267 @param profiles: profile names from which nodes must be deleted.
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1268 None to remove nodes from ALL profiles
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1269 @param services: JIDs of pubsub services from which nodes must be deleted.
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1270 None to remove nodes from ALL services
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1271 @param names: names of nodes which must be deleted.
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1272 None to remove ALL nodes whatever is their names
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1273 """
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1274 stmt = delete(PubsubNode)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1275 if profiles is not None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1276 stmt = stmt.where(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1277 PubsubNode.profile.in_([self.profiles[p] for p in profiles])
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1278 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1279 if services is not None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1280 stmt = stmt.where(PubsubNode.service.in_(services))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1281 if names is not None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1282 stmt = stmt.where(PubsubNode.name.in_(names))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1283 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1284 await session.execute(stmt)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1285 await session.commit()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1286
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1287 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1288 async def cache_pubsub_items(
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1289 self,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1290 client: SatXMPPEntity,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1291 node: PubsubNode,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1292 items: List[domish.Element],
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1293 parsed_items: Optional[List[dict]] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1294 ) -> None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1295 """Add items to database, using an upsert taking care of "updated" field"""
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1296 if parsed_items is not None and len(items) != len(parsed_items):
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1297 raise exceptions.InternalError(
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1298 "parsed_items must have the same lenght as items"
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1299 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1300 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1301 async with session.begin():
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1302 for idx, item in enumerate(items):
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1303 parsed = parsed_items[idx] if parsed_items else None
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1304 stmt = (
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1305 insert(PubsubItem)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1306 .values(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1307 node_id=node.id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1308 name=item["id"],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1309 data=item,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1310 parsed=parsed,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1311 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1312 .on_conflict_do_update(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1313 index_elements=(PubsubItem.node_id, PubsubItem.name),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1314 set_={
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1315 PubsubItem.data: item,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1316 PubsubItem.parsed: parsed,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1317 PubsubItem.updated: now(),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1318 },
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1319 )
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1320 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1321 await session.execute(stmt)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1322 await session.commit()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1323
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1324 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1325 async def delete_pubsub_items(
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1326 self, node: PubsubNode, items_names: Optional[List[str]] = None
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1327 ) -> None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1328 """Delete items cached for a node
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1329
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1330 @param node: node from which items must be deleted
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1331 @param items_names: names of items to delete
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1332 if None, ALL items will be deleted
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1333 """
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1334 stmt = delete(PubsubItem)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1335 if node is not None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1336 if isinstance(node, list):
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1337 stmt = stmt.where(PubsubItem.node_id.in_([n.id for n in node]))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1338 else:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1339 stmt = stmt.filter_by(node_id=node.id)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1340 if items_names is not None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1341 stmt = stmt.where(PubsubItem.name.in_(items_names))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1342 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1343 await session.execute(stmt)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1344 await session.commit()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1345
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1346 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1347 async def purge_pubsub_items(
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1348 self,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1349 services: Optional[List[jid.JID]] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1350 names: Optional[List[str]] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1351 types: Optional[List[str]] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1352 subtypes: Optional[List[str]] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1353 profiles: Optional[List[str]] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1354 created_before: Optional[datetime] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1355 updated_before: Optional[datetime] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1356 ) -> None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1357 """Delete items cached for a node
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1358
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1359 @param node: node from which items must be deleted
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1360 @param items_names: names of items to delete
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1361 if None, ALL items will be deleted
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1362 """
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1363 stmt = delete(PubsubItem)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1364 node_fields = {
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1365 "service": services,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1366 "name": names,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1367 "type_": types,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1368 "subtype": subtypes,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1369 }
3744
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1370 if profiles is not None:
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1371 node_fields["profile_id"] = [self.profiles[p] for p in profiles]
658ddbabaf36 core (memory/sqla): new table/mapping to handle Pubsub node subscriptions:
Goffi <goffi@goffi.org>
parents: 3720
diff changeset
1372
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1373 if any(x is not None for x in node_fields.values()):
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1374 sub_q = select(PubsubNode.id)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1375 for col, values in node_fields.items():
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1376 if values is None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1377 continue
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1378 sub_q = sub_q.where(getattr(PubsubNode, col).in_(values))
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1379 stmt = stmt.where(PubsubItem.node_id.in_(sub_q)).execution_options(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1380 synchronize_session=False
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1381 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1382
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1383 if created_before is not None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1384 stmt = stmt.where(PubsubItem.created < created_before)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1385
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1386 if updated_before is not None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1387 stmt = stmt.where(PubsubItem.updated < updated_before)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1388
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1389 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1390 await session.execute(stmt)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1391 await session.commit()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1392
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1393 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1394 async def get_items(
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1395 self,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1396 node: PubsubNode,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1397 max_items: Optional[int] = None,
3753
10b71e3526bd core (memory/sqla): add attribute to filter on `item_ids` in `getItems`
Goffi <goffi@goffi.org>
parents: 3744
diff changeset
1398 item_ids: Optional[list[str]] = None,
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1399 before: Optional[str] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1400 after: Optional[str] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1401 from_index: Optional[int] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1402 order_by: Optional[List[str]] = None,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1403 desc: bool = True,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1404 force_rsm: bool = False,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1405 ) -> Tuple[List[PubsubItem], dict]:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1406 """Get Pubsub Items from cache
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1407
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1408 @param node: retrieve items from this node (must be synchronised)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1409 @param max_items: maximum number of items to retrieve
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1410 @param before: get items which are before the item with this name in given order
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1411 empty string is not managed here, use desc order to reproduce RSM
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1412 behaviour.
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1413 @param after: get items which are after the item with this name in given order
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1414 @param from_index: get items with item index (as defined in RSM spec)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1415 starting from this number
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1416 @param order_by: sorting order of items (one of C.ORDER_BY_*)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1417 @param desc: direction or ordering
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1418 @param force_rsm: if True, force the use of RSM worklow.
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1419 RSM workflow is automatically used if any of before, after or
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1420 from_index is used, but if only RSM max_items is used, it won't be
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1421 used by default. This parameter let's use RSM workflow in this
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1422 case. Note that in addition to RSM metadata, the result will not be
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1423 the same (max_items without RSM will returns most recent items,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1424 i.e. last items in modification order, while max_items with RSM
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1425 will return the oldest ones (i.e. first items in modification
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1426 order).
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1427 to be used when max_items is used from RSM
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1428 """
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1429
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1430 metadata = {
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1431 "service": node.service,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1432 "node": node.name,
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1433 "uri": uri.build_xmpp_uri(
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1434 "pubsub",
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1435 path=node.service.full(),
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1436 node=node.name,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1437 ),
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1438 }
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1439 if max_items is None:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1440 max_items = 20
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1441
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1442 use_rsm = any((before, after, from_index is not None))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1443 if force_rsm and not use_rsm:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1444 #
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1445 use_rsm = True
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1446 from_index = 0
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1447
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1448 stmt = select(PubsubItem).filter_by(node_id=node.id).limit(max_items)
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1449
3753
10b71e3526bd core (memory/sqla): add attribute to filter on `item_ids` in `getItems`
Goffi <goffi@goffi.org>
parents: 3744
diff changeset
1450 if item_ids is not None:
10b71e3526bd core (memory/sqla): add attribute to filter on `item_ids` in `getItems`
Goffi <goffi@goffi.org>
parents: 3744
diff changeset
1451 stmt = stmt.where(PubsubItem.name.in_(item_ids))
10b71e3526bd core (memory/sqla): add attribute to filter on `item_ids` in `getItems`
Goffi <goffi@goffi.org>
parents: 3744
diff changeset
1452
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1453 if not order_by:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1454 order_by = [C.ORDER_BY_MODIFICATION]
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1455
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1456 order = []
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1457 for order_type in order_by:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1458 if order_type == C.ORDER_BY_MODIFICATION:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1459 if desc:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1460 order.extend((PubsubItem.updated.desc(), PubsubItem.id.desc()))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1461 else:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1462 order.extend((PubsubItem.updated.asc(), PubsubItem.id.asc()))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1463 elif order_type == C.ORDER_BY_CREATION:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1464 if desc:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1465 order.append(PubsubItem.id.desc())
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1466 else:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1467 order.append(PubsubItem.id.asc())
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1468 else:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1469 raise exceptions.InternalError(f"Unknown order type {order_type!r}")
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1470
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1471 stmt = stmt.order_by(*order)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1472
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1473 if use_rsm:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1474 # CTE to have result row numbers
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1475 row_num_q = select(
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1476 PubsubItem.id,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1477 PubsubItem.name,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1478 # row_number starts from 1, but RSM index must start from 0
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1479 (func.row_number().over(order_by=order) - 1).label("item_index"),
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1480 ).filter_by(node_id=node.id)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1481
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1482 row_num_cte = row_num_q.cte()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1483
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1484 if max_items > 0:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1485 # as we can't simply use PubsubItem.id when we order by modification,
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1486 # we need to use row number
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1487 item_name = before or after
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1488 row_num_limit_q = (
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1489 select(row_num_cte.c.item_index).where(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1490 row_num_cte.c.name == item_name
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1491 )
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1492 ).scalar_subquery()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1493
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1494 stmt = (
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1495 select(row_num_cte.c.item_index, PubsubItem)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1496 .join(row_num_cte, PubsubItem.id == row_num_cte.c.id)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1497 .limit(max_items)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1498 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1499 if before:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1500 stmt = stmt.where(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1501 row_num_cte.c.item_index < row_num_limit_q
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1502 ).order_by(row_num_cte.c.item_index.desc())
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1503 elif after:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1504 stmt = stmt.where(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1505 row_num_cte.c.item_index > row_num_limit_q
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1506 ).order_by(row_num_cte.c.item_index.asc())
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1507 else:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1508 stmt = stmt.where(row_num_cte.c.item_index >= from_index).order_by(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1509 row_num_cte.c.item_index.asc()
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1510 )
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1511 # from_index is used
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1512
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1513 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1514 if max_items == 0:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1515 items = result = []
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1516 else:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1517 result = await session.execute(stmt)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1518 result = result.all()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1519 if before:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1520 result.reverse()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1521 items = [row[-1] for row in result]
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1522 rows_count = (
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1523 await session.execute(row_num_q.with_only_columns(count()))
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1524 ).scalar_one()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1525
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1526 try:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1527 index = result[0][0]
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1528 except IndexError:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1529 index = None
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1530
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1531 try:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1532 first = result[0][1].name
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1533 except IndexError:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1534 first = None
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1535 last = None
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1536 else:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1537 last = result[-1][1].name
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1538
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1539 metadata["rsm"] = {
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1540 k: v
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1541 for k, v in {
3719
cf930bb282ac memory (sqla): don't set keys with None as value for RSM in `getItems`
Goffi <goffi@goffi.org>
parents: 3673
diff changeset
1542 "index": index,
cf930bb282ac memory (sqla): don't set keys with None as value for RSM in `getItems`
Goffi <goffi@goffi.org>
parents: 3673
diff changeset
1543 "count": rows_count,
cf930bb282ac memory (sqla): don't set keys with None as value for RSM in `getItems`
Goffi <goffi@goffi.org>
parents: 3673
diff changeset
1544 "first": first,
cf930bb282ac memory (sqla): don't set keys with None as value for RSM in `getItems`
Goffi <goffi@goffi.org>
parents: 3673
diff changeset
1545 "last": last,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1546 }.items()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1547 if v is not None
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1548 }
3720
40a6374fcd44 memory (sqla): fix `complete` setting when `index` is `None` in `getItems`
Goffi <goffi@goffi.org>
parents: 3719
diff changeset
1549 metadata["complete"] = (index or 0) + len(result) == rows_count
3595
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1550
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1551 return items, metadata
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1552
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1553 async with self.session() as session:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1554 result = await session.execute(stmt)
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1555
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1556 result = result.scalars().all()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1557 if desc:
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1558 result.reverse()
7510648e8e3a core (memory/sqla): methods to manipulate pubsub tables
Goffi <goffi@goffi.org>
parents: 3583
diff changeset
1559 return result, metadata
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1560
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1561 def _get_sqlite_path(self, path: List[Union[str, int]]) -> str:
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1562 """generate path suitable to query JSON element with SQLite"""
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1563 return f"${''.join(f'[{p}]' if isinstance(p, int) else f'.{p}' for p in path)}"
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1564
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1565 @aio
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1566 async def search_pubsub_items(
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1567 self,
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1568 query: dict,
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1569 ) -> Tuple[List[PubsubItem]]:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1570 """Search for pubsub items in cache
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1571
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1572 @param query: search terms. Keys can be:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1573 :fts (str):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1574 Full-Text Search query. Currently SQLite FT5 engine is used, its query
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1575 syntax can be used, see `FTS5 Query documentation
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1576 <https://sqlite.org/fts5.html#full_text_query_syntax>`_
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1577 :profiles (list[str]):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1578 filter on nodes linked to those profiles
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1579 :nodes (list[str]):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1580 filter on nodes with those names
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1581 :services (list[jid.JID]):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1582 filter on nodes from those services
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1583 :types (list[str|None]):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1584 filter on nodes with those types. None can be used to filter on nodes with
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1585 no type set
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1586 :subtypes (list[str|None]):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1587 filter on nodes with those subtypes. None can be used to filter on nodes with
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1588 no subtype set
3754
af485e8afe03 core (memory/sqla): `searchPubsubItems` can now filter on item names
Goffi <goffi@goffi.org>
parents: 3753
diff changeset
1589 :names (list[str]):
af485e8afe03 core (memory/sqla): `searchPubsubItems` can now filter on item names
Goffi <goffi@goffi.org>
parents: 3753
diff changeset
1590 filter on items with those names
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1591 :parsed (list[dict]):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1592 Filter on a parsed data field. The dict must contain 3 keys: ``path``
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1593 which is a list of str or int giving the path to the field of interest
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1594 (str for a dict key, int for a list index), ``operator`` with indicate the
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1595 operator to use to check the condition, and ``value`` which depends of
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1596 field type and operator.
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1597
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1598 See documentation for details on operators (it's currently explained at
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1599 ``doc/libervia-cli/pubsub_cache.rst`` in ``search`` command
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1600 documentation).
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1601
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1602 :order-by (list[dict]):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1603 Indicates how to order results. The dict can contain either a ``order``
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1604 for a well-know order or a ``path`` for a parsed data field path
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1605 (``order`` and ``path`` can't be used at the same time), an an optional
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1606 ``direction`` which can be ``asc`` or ``desc``. See documentation for
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1607 details on well-known orders (it's currently explained at
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1608 ``doc/libervia-cli/pubsub_cache.rst`` in ``search`` command
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1609 documentation).
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1610
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1611 :index (int):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1612 starting index of items to return from the query result. It's translated
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1613 to SQL's OFFSET
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1614
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1615 :limit (int):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1616 maximum number of items to return. It's translated to SQL's LIMIT.
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1617
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1618 @result: found items (the ``node`` attribute will be filled with suitable
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1619 PubsubNode)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1620 """
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1621 # TODO: FTS and parsed data filters use SQLite specific syntax
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1622 # when other DB engines will be used, this will have to be adapted
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1623 stmt = select(PubsubItem)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1624
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1625 # Full-Text Search
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1626 fts = query.get("fts")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1627 if fts:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1628 fts_select = (
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1629 text("SELECT rowid, rank FROM pubsub_items_fts(:fts_query)")
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1630 .bindparams(fts_query=fts)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1631 .columns(rowid=Integer)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1632 .subquery()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1633 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1634 stmt = stmt.select_from(fts_select).outerjoin(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1635 PubsubItem, fts_select.c.rowid == PubsubItem.id
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1636 )
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1637
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1638 # node related filters
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1639 profiles = query.get("profiles")
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1640 if profiles or any(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1641 query.get(k) for k in ("nodes", "services", "types", "subtypes")
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1642 ):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1643 stmt = stmt.join(PubsubNode).options(contains_eager(PubsubItem.node))
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1644 if profiles:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1645 try:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1646 stmt = stmt.where(
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1647 PubsubNode.profile_id.in_(self.profiles[p] for p in profiles)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1648 )
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1649 except KeyError as e:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1650 raise exceptions.ProfileUnknownError(
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1651 f"This profile doesn't exist: {e.args[0]!r}"
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1652 )
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1653 for key, attr in (
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1654 ("nodes", "name"),
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1655 ("services", "service"),
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1656 ("types", "type_"),
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1657 ("subtypes", "subtype"),
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1658 ):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1659 value = query.get(key)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1660 if not value:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1661 continue
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1662 if key in ("types", "subtypes") and None in value:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1663 # NULL can't be used with SQL's IN, so we have to add a condition with
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1664 # IS NULL, and use a OR if there are other values to check
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1665 value.remove(None)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1666 condition = getattr(PubsubNode, attr).is_(None)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1667 if value:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1668 condition = or_(getattr(PubsubNode, attr).in_(value), condition)
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1669 else:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1670 condition = getattr(PubsubNode, attr).in_(value)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1671 stmt = stmt.where(condition)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1672 else:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1673 stmt = stmt.options(selectinload(PubsubItem.node))
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1674
3754
af485e8afe03 core (memory/sqla): `searchPubsubItems` can now filter on item names
Goffi <goffi@goffi.org>
parents: 3753
diff changeset
1675 # names
af485e8afe03 core (memory/sqla): `searchPubsubItems` can now filter on item names
Goffi <goffi@goffi.org>
parents: 3753
diff changeset
1676 names = query.get("names")
af485e8afe03 core (memory/sqla): `searchPubsubItems` can now filter on item names
Goffi <goffi@goffi.org>
parents: 3753
diff changeset
1677 if names:
af485e8afe03 core (memory/sqla): `searchPubsubItems` can now filter on item names
Goffi <goffi@goffi.org>
parents: 3753
diff changeset
1678 stmt = stmt.where(PubsubItem.name.in_(names))
af485e8afe03 core (memory/sqla): `searchPubsubItems` can now filter on item names
Goffi <goffi@goffi.org>
parents: 3753
diff changeset
1679
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1680 # parsed data filters
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1681 parsed = query.get("parsed", [])
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1682 for filter_ in parsed:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1683 try:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1684 path = filter_["path"]
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1685 operator = filter_["op"]
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1686 value = filter_["value"]
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1687 except KeyError as e:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1688 raise ValueError(
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1689 f'missing mandatory key {e.args[0]!r} in "parsed" filter'
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1690 )
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1691 try:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1692 op_attr = OP_MAP[operator]
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1693 except KeyError:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1694 raise ValueError(f"invalid operator: {operator!r}")
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1695 sqlite_path = self._get_sqlite_path(path)
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1696 if operator in ("overlap", "ioverlap", "disjoint", "idisjoint"):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1697 col = literal_column("json_each.value")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1698 if operator[0] == "i":
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1699 col = func.lower(col)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1700 value = [str(v).lower() for v in value]
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1701 condition = (
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1702 select(1)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1703 .select_from(func.json_each(PubsubItem.parsed, sqlite_path))
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1704 .where(col.in_(value))
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1705 ).scalar_subquery()
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1706 if operator in ("disjoint", "idisjoint"):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1707 condition = condition.is_(None)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1708 stmt = stmt.where(condition)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1709 elif operator == "between":
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1710 try:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1711 left, right = value
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1712 except (ValueError, TypeError):
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1713 raise ValueError(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1714 _(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1715 'invalid value for "between" filter, you must use a 2 items '
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1716 "array: {value!r}"
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1717 ).format(value=value)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1718 )
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1719 col = func.json_extract(PubsubItem.parsed, sqlite_path)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1720 stmt = stmt.where(col.between(left, right))
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1721 else:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1722 # we use func.json_extract instead of generic JSON way because SQLAlchemy
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1723 # add a JSON_QUOTE to the value, and we want SQL value
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1724 col = func.json_extract(PubsubItem.parsed, sqlite_path)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1725 stmt = stmt.where(getattr(col, op_attr)(value))
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1726
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1727 # order
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1728 order_by = query.get("order-by") or [{"order": "creation"}]
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1729
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1730 for order_data in order_by:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1731 order, path = order_data.get("order"), order_data.get("path")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1732 if order and path:
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1733 raise ValueError(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1734 _(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1735 '"order" and "path" can\'t be used at the same time in '
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1736 '"order-by" data'
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1737 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1738 )
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1739 if order:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1740 if order == "creation":
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1741 col = PubsubItem.id
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1742 elif order == "modification":
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1743 col = PubsubItem.updated
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1744 elif order == "item_id":
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1745 col = PubsubItem.name
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1746 elif order == "rank":
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1747 if not fts:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1748 raise ValueError(
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1749 "'rank' order can only be used with Full-Text Search (fts)"
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1750 )
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1751 col = literal_column("rank")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1752 else:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1753 raise NotImplementedError(f"Unknown {order!r} order")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1754 else:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1755 # we have a JSON path
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4003
diff changeset
1756 # sqlite_path = self._get_sqlite_path(path)
3664
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1757 col = PubsubItem.parsed[path]
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1758 direction = order_data.get("direction", "ASC").lower()
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1759 if not direction in ("asc", "desc"):
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1760 raise ValueError(f"Invalid order-by direction: {direction!r}")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1761 stmt = stmt.order_by(getattr(col, direction)())
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1762
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1763 # offset, limit
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1764 index = query.get("index")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1765 if index:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1766 stmt = stmt.offset(index)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1767 limit = query.get("limit")
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1768 if limit:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1769 stmt = stmt.limit(limit)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1770
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1771 async with self.session() as session:
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1772 result = await session.execute(stmt)
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1773
9ae6ec74face memory (sqla): implement `searchPubsubItems`:
Goffi <goffi@goffi.org>
parents: 3638
diff changeset
1774 return result.scalars().all()
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1775
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1776 # Notifications
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1777
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1778 @aio
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1779 async def add_notification(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1780 self,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1781 client: Optional[SatXMPPEntity],
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1782 type_: NotificationType,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1783 body_plain: str,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1784 body_rich: Optional[str] = None,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1785 title: Optional[str] = None,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1786 requires_action: bool = False,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1787 priority: NotificationPriority = NotificationPriority.MEDIUM,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1788 expire_at: Optional[float] = None,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1789 extra: Optional[dict] = None,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1790 ) -> Notification:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1791 """Add a new notification to the DB.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1792
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1793 @param client: client associated with the notification. If None, the notification
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1794 will be global.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1795 @param type_: type of the notification.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1796 @param body_plain: plain text body.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1797 @param body_rich: rich text (XHTML) body.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1798 @param title: optional title.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1799 @param requires_action: True if the notification requires user action (e.g. a
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1800 dialog need to be answered).
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1801 @priority: how urgent the notification is
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1802 @param expire_at: expiration timestamp for the notification.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1803 @param extra: additional data.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1804 @return: created Notification
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1805 """
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1806 profile_id = self.profiles[client.profile] if client else None
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1807 notification = Notification(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1808 profile_id=profile_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1809 type=type_,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1810 body_plain=body_plain,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1811 body_rich=body_rich,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1812 requires_action=requires_action,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1813 priority=priority,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1814 expire_at=expire_at,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1815 title=title,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1816 extra_data=extra,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1817 status=NotificationStatus.new,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1818 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1819 async with self.session() as session:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1820 async with session.begin():
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1821 session.add(notification)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1822 return notification
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1823
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1824 @aio
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1825 async def update_notification(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1826 self, client: SatXMPPEntity, notification_id: int, **kwargs
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1827 ) -> None:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1828 """Update an existing notification.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1829
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1830 @param client: client associated with the notification.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1831 @param notification_id: ID of the notification to update.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1832 """
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1833 profile_id = self.profiles[client.profile]
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1834 async with self.session() as session:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1835 await session.execute(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1836 update(Notification)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1837 .where(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1838 and_(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1839 Notification.profile_id == profile_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1840 Notification.id == notification_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1841 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1842 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1843 .values(**kwargs)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1844 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1845 await session.commit()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1846
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1847 @aio
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1848 async def get_notifications(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1849 self,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1850 client: SatXMPPEntity,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1851 type_: Optional[NotificationType] = None,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1852 status: Optional[NotificationStatus] = None,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1853 requires_action: Optional[bool] = None,
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4212
diff changeset
1854 min_priority: Optional[int] = None,
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1855 ) -> List[Notification]:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1856 """Retrieve all notifications for a given profile with optional filters.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1857
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1858 @param client: client associated with the notifications.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1859 @param type_: filter by type of the notification.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1860 @param status: filter by status of the notification.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1861 @param requires_action: filter by notifications that require user action.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1862 @param min_priority: filter by minimum priority value.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1863 @return: list of matching Notification instances.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1864 """
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1865 profile_id = self.profiles[client.profile]
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4212
diff changeset
1866 filters = [
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4212
diff changeset
1867 or_(Notification.profile_id == profile_id, Notification.profile_id.is_(None))
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4212
diff changeset
1868 ]
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1869
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1870 if type_:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1871 filters.append(Notification.type == type_)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1872 if status:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1873 filters.append(Notification.status == status)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1874 if requires_action is not None:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1875 filters.append(Notification.requires_action == requires_action)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1876 if min_priority:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1877 filters.append(Notification.priority >= min_priority)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1878
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1879 async with self.session() as session:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1880 result = await session.execute(
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4212
diff changeset
1881 select(Notification).where(and_(*filters)).order_by(Notification.id)
4130
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1882 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1883 return result.scalars().all()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1884
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1885 @aio
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1886 async def delete_notification(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1887 self, client: Optional[SatXMPPEntity], notification_id: str
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1888 ) -> None:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1889 """Delete a notification by its profile and id.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1890
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1891 @param client: client associated with the notification. If None, profile_id will be NULL.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1892 @param notification_id: ID of the notification to delete.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1893 """
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1894 profile_id = self.profiles[client.profile] if client else None
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1895 async with self.session() as session:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1896 await session.execute(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1897 delete(Notification).where(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1898 and_(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1899 Notification.profile_id == profile_id,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1900 Notification.id == int(notification_id),
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1901 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1902 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1903 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1904 await session.commit()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1905
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1906 @aio
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1907 async def clean_expired_notifications(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1908 self, client: Optional[SatXMPPEntity], limit_timestamp: Optional[float] = None
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1909 ) -> None:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1910 """Cleans expired notifications and older profile-specific notifications.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1911
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1912 - Removes all notifications where the expiration timestamp has passed,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1913 irrespective of their profile.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1914 - If a limit_timestamp is provided, removes older notifications with a profile set
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1915 (i.e., not global notifications) that do not require user action. If client is
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1916 provided, only remove notification for this profile.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1917
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1918 @param client: if provided, only expire notification for this client (in addition
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1919 to truly expired notifications for everybody).
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1920 @param limit_timestamp: Timestamp limit for older notifications. If None, only
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1921 truly expired notifications are removed.
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1922 """
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1923
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1924 # Delete truly expired notifications
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1925 expired_condition = Notification.expire_at < time.time()
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1926
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1927 # Delete older profile-specific notifications (created before the limit_timestamp)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1928 if client is None:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1929 profile_condition = Notification.profile_id.isnot(None)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1930 else:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1931 profile_condition = Notification.profile_id == self.profiles[client.profile]
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1932 older_condition = and_(
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1933 profile_condition,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1934 Notification.timestamp < limit_timestamp if limit_timestamp else False,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1935 Notification.requires_action == False,
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1936 )
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1937
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1938 # Combine the conditions
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1939 conditions = or_(expired_condition, older_condition)
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1940
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1941 async with self.session() as session:
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1942 await session.execute(delete(Notification).where(conditions))
02f0adc745c6 core: notifications implementation, first draft:
Goffi <goffi@goffi.org>
parents: 4092
diff changeset
1943 await session.commit()