diff --git a/changelog.d/5383.feature b/changelog.d/5383.feature
new file mode 100644
index 0000000000..5d084cf0b2
--- /dev/null
+++ b/changelog.d/5383.feature
@@ -0,0 +1 @@
+Add ability to change Docker containers [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) with the `TZ` variable.
diff --git a/changelog.d/5507.bugfix b/changelog.d/5507.bugfix
new file mode 100644
index 0000000000..70452aa146
--- /dev/null
+++ b/changelog.d/5507.bugfix
@@ -0,0 +1 @@
+Fix bug where clients could tight loop calling `/sync` for a period.
diff --git a/changelog.d/5585.misc b/changelog.d/5585.misc
new file mode 100644
index 0000000000..6be06d4d0b
--- /dev/null
+++ b/changelog.d/5585.misc
@@ -0,0 +1 @@
+Synapse can now handle RestServlets that return coroutines.
diff --git a/changelog.d/5586.bugfix b/changelog.d/5586.bugfix
new file mode 100644
index 0000000000..c0b1ecf81a
--- /dev/null
+++ b/changelog.d/5586.bugfix
@@ -0,0 +1 @@
+Fixed m.login.jwt using unregistred user_id and added pyjwt>=1.6.4 as jwt conditional dependencies. Contributed by Pau Rodriguez-Estivill.
diff --git a/changelog.d/5587.feature b/changelog.d/5587.feature
new file mode 100644
index 0000000000..ec1503860a
--- /dev/null
+++ b/changelog.d/5587.feature
@@ -0,0 +1 @@
+Add --no-daemonize option to run synapse in the foreground, per issue #4130. Contributed by Soham Gumaste.
\ No newline at end of file
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 0939cadf39..79276209f6 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -66,6 +66,7 @@ RUN apk add --no-cache --virtual .runtime_deps \
libpq \
zlib \
su-exec \
+ tzdata \
xmlsec
COPY --from=builder /install /usr/local
diff --git a/docker/README.md b/docker/README.md
index b62417c281..46bb9d2d99 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -63,7 +63,6 @@ The following environment variables are supported in `generate` mode:
* `UID`, `GID`: the user id and group id to use for creating the data
directories. Defaults to `991`, `991`.
-
## Running synapse
Once you have a valid configuration file, you can start synapse as follows:
@@ -91,6 +90,7 @@ The following environment variables are supported in run mode:
* `SYNAPSE_CONFIG_PATH`: path to the config file. Defaults to
`<SYNAPSE_CONFIG_DIR>/homeserver.yaml`.
* `UID`, `GID`: the user and group id to run Synapse as. Defaults to `991`, `991`.
+* `TZ`: the [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) the container will run with. Defaults to `UTC`.
## TLS support
diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py
index 5204073a38..c80dc2eba0 100644
--- a/synapse/handlers/presence.py
+++ b/synapse/handlers/presence.py
@@ -1017,11 +1017,28 @@ class PresenceEventSource(object):
if from_key is not None:
from_key = int(from_key)
+ max_token = self.store.get_current_presence_token()
+ if from_key == max_token:
+ # This is necessary as due to the way stream ID generators work
+ # we may get updates that have a stream ID greater than the max
+ # token (e.g. max_token is N but stream generator may return
+ # results for N+2, due to N+1 not having finished being
+ # persisted yet).
+ #
+ # This is usually fine, as it just means that we may send down
+ # some presence updates multiple times. However, we need to be
+ # careful that the sync stream either actually does make some
+ # progress or doesn't return, otherwise clients will end up
+ # tight looping calling /sync due to it immediately returning
+ # the same token repeatedly.
+ #
+ # Hence this guard where we just return nothing so that the sync
+ # doesn't return. C.f. #5503.
+ defer.returnValue(([], max_token))
+
presence = self.get_presence_handler()
stream_change_cache = self.store.presence_stream_cache
- max_token = self.store.get_current_presence_token()
-
users_interested_in = yield self._get_interested_in(user, explicit_room_id)
user_ids_changed = set()
diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py
index 3051b2171b..f961178235 100644
--- a/synapse/rest/client/v1/login.py
+++ b/synapse/rest/client/v1/login.py
@@ -323,12 +323,12 @@ class LoginRestServlet(RestServlet):
raise LoginError(401, "Invalid JWT", errcode=Codes.UNAUTHORIZED)
user_id = UserID(user, self.hs.hostname).to_string()
+ device_id = login_submission.get("device_id")
+ initial_display_name = login_submission.get("initial_device_display_name")
auth_handler = self.auth_handler
registered_user_id = yield auth_handler.check_user_exists(user_id)
if registered_user_id:
- device_id = login_submission.get("device_id")
- initial_display_name = login_submission.get("initial_device_display_name")
device_id, access_token = yield self.registration_handler.register_device(
registered_user_id, device_id, initial_display_name
)
@@ -342,11 +342,8 @@ class LoginRestServlet(RestServlet):
user_id, access_token = (
yield self.registration_handler.register(localpart=user)
)
-
- device_id = login_submission.get("device_id")
- initial_display_name = login_submission.get("initial_device_display_name")
device_id, access_token = yield self.registration_handler.register_device(
- registered_user_id, device_id, initial_display_name
+ user_id, device_id, initial_display_name
)
result = {
diff --git a/synapse/rest/consent/consent_resource.py b/synapse/rest/consent/consent_resource.py
index 624c42441e..1ddf9997ff 100644
--- a/synapse/rest/consent/consent_resource.py
+++ b/synapse/rest/consent/consent_resource.py
@@ -23,6 +23,8 @@ from six.moves import http_client
import jinja2
from jinja2 import TemplateNotFound
+from twisted.internet import defer
+
from synapse.api.errors import NotFoundError, StoreError, SynapseError
from synapse.config import ConfigError
from synapse.http.server import (
@@ -139,7 +141,7 @@ class ConsentResource(DirectServeResource):
else:
qualified_user_id = UserID(username, self.hs.hostname).to_string()
- u = await self.store.get_user_by_id(qualified_user_id)
+ u = await defer.maybeDeferred(self.store.get_user_by_id, qualified_user_id)
if u is None:
raise NotFoundError("Unknown user")
diff --git a/synctl b/synctl
index 30d751236f..794de99ea3 100755
--- a/synctl
+++ b/synctl
@@ -150,8 +150,9 @@ def main():
parser.add_argument(
"--no-daemonize",
action="store_false",
+ dest="daemonize",
help="Run synapse in the foreground for debugging. "
- "Will work only if the daemonize option is not set in the config."
+ "Will work only if the daemonize option is not set in the config.",
)
options = parser.parse_args()
@@ -159,7 +160,7 @@ def main():
if options.worker and options.all_processes:
write('Cannot use "--worker" with "--all-processes"', stream=sys.stderr)
sys.exit(1)
- if options.no_daemonize and options.all_processes:
+ if not options.daemonize and options.all_processes:
write('Cannot use "--no-daemonize" with "--all-processes"', stream=sys.stderr)
sys.exit(1)
@@ -169,9 +170,8 @@ def main():
write(
"No config file found\n"
"To generate a config file, run '%s -c %s --generate-config"
- " --server-name=<server name> --report-stats=<yes/no>'\n" % (
- " ".join(SYNAPSE), options.configfile,
- ),
+ " --server-name=<server name> --report-stats=<yes/no>'\n"
+ % (" ".join(SYNAPSE), options.configfile),
stream=sys.stderr,
)
sys.exit(1)
@@ -289,7 +289,7 @@ def main():
# Check if synapse is already running
if os.path.exists(pidfile) and pid_running(int(open(pidfile).read())):
abort("synapse.app.homeserver already running")
- start(configfile, bool(options.no_daemonize))
+ start(configfile, bool(options.daemonize))
for worker in workers:
env = os.environ.copy()
|