Skip to content

Commit

Permalink
Merge pull request #1935 from compdemocracy/edge
Browse files Browse the repository at this point in the history
Edge to Stable for Prod deploy
  • Loading branch information
tevko authored Feb 25, 2025
2 parents b8360f4 + 56ed5c2 commit f0454cd
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 38 deletions.
6 changes: 4 additions & 2 deletions client-admin/src/components/conversation-admin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ class ConversationAdminContainer extends React.Component {
this.resetMetadata()
}

componentDidUpdate() {
this.loadZidMetadata()
componentDidUpdate(prevProps) {
if (prevProps.match.params.conversation_id !== this.props.match.params.conversation_id) {
this.loadZidMetadata()
}
}

render() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@ class ReportsList extends React.Component {
})
})
}

componentDidMount() {
const { zid_metadata } = this.props

// eslint-disable-next-line react/prop-types

this.props.dispatch(
populateZidMetadataStore(this.props.match.params.conversation_id)
)
Expand All @@ -47,9 +46,13 @@ class ReportsList extends React.Component {
}
}

componentDidUpdate() {
componentDidUpdate(prevProps) {
// Only call getData() if is_mod changed from false/undefined to true
const { zid_metadata } = this.props
if (zid_metadata?.is_mod) {
const prevIsMod = prevProps.zid_metadata?.is_mod
const currentIsMod = zid_metadata?.is_mod

if (!prevIsMod && currentIsMod) {
this.getData()
}
}
Expand Down Expand Up @@ -105,6 +108,7 @@ class ReportsList extends React.Component {
}

ReportsList.propTypes = {
dispatch: PropTypes.func,
match: PropTypes.shape({
params: PropTypes.shape({
conversation_id: PropTypes.string
Expand Down
34 changes: 24 additions & 10 deletions client-admin/src/components/conversation-admin/stats/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,41 @@ class ConversationStats extends React.Component {
populateZidMetadataStore(match.params.conversation_id)
)

if (zid_metadata.is_mod) {
this.loadStats()
this.getStatsRepeatedly = setInterval(() => {
this.loadStats()
}, 10000)
if (zid_metadata?.is_mod) {
this.startPolling()
}
}

componentDidUpdate() {
componentDidUpdate(prevProps) {
const { zid_metadata } = this.props
if (zid_metadata?.is_mod) {
this.loadStats()
const prevIsMod = prevProps.zid_metadata?.is_mod
const currentIsMod = zid_metadata?.is_mod

// Start polling only when is_mod changes from false to true
if (!prevIsMod && currentIsMod) {
this.startPolling()
}
}

componentWillUnmount() {
const { zid_metadata } = this.props
if (this.getStatsRepeatedly) {
clearInterval(this.getStatsRepeatedly)
}
}

if (zid_metadata.is_mod) {
startPolling() {
// Clear any existing interval
if (this.getStatsRepeatedly) {
clearInterval(this.getStatsRepeatedly)
}

// Initial load
this.loadStats()

// Start polling
this.getStatsRepeatedly = setInterval(() => {
this.loadStats()
}, 10000)
}

render() {
Expand Down
2 changes: 1 addition & 1 deletion client-participation/js/strings/en_us.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ s.helpWhatDoIDoTitle = " What do I do?";
s.helpWhatDoIDo =
"Vote on other people's statements by clicking 'agree' or 'disagree'. Write a statement (keep each to a single idea). Invite your friends to the conversation!";
s.writeCommentHelpText =
"Are your perspectives or experiences missing from the conversation? If so,</b>add them </b> in the box below — </b>one at a time</b>.";
"Are your perspectives or experiences missing from the conversation? If so, </b>add them </b> in the box below — </b>one at a time</b>.";
s.helpWriteListIntro = "What makes for a good statement?";
s.helpWriteListStandalone = "A stand-alone idea";
s.helpWriteListRaisNew = "A new perspective, experience, or issue";
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ services:
polis_tag: ${TAG:-dev}
environment:
- DATABASE_URL=${DATABASE_URL}
- LOGGING_LEVEL=${MATH_LOG_LEVEL:-warn}
- MATH_ENV=${MATH_ENV:-prod}
- WEBSERVER_USERNAME=${WEBSERVER_USERNAME}
- WEBSERVER_PASS=${WEBSERVER_PASS}
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ If you are deploying to a custom domain (not `pol.is`) then you need to update b
- **`EMAIL_TRANSPORT_TYPES`** comma-separated list of email services to use (see [Email Transports](#email-transports) below)
- **`GIT_HASH`** Set programmatically using `git rev-parse HEAD` (e.g. in `Makefile`) to tag docker container versions and other release assets. Can be left blank.
- **`MATH_ENV`** Set to `prod` (default), `preprod`, `dev` or arbitrary feature flag. In cases where a single database is used for multiple environments, this value is used by the API service to request the correct data. (Using a single DB for multiple environments in this fashion is no longer recommended, and so the default value of `prod` is recommended.)
- **`MATH_LOG_LEVEL`** Used by the math service to determine how much logging to output. Reasonable values are `debug`, `info`, `warn`, and `error`. Defaults to `warn`.
- **`SERVER_ENV_FILE`** The name of an environment file to be passed into the API Server container by docker compose. Defaults to `.env` if left blank. Used especially for building a `test` version of the project for end-to-end testing.
- **`SERVER_LOG_LEVEL`** Used by Winston.js in the API server to determine how much logging to output. Reasonable values are `debug`, `info`, and `error`. Defaults to `info`.

Expand Down
2 changes: 2 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ EMAIL_TRANSPORT_TYPES=maildev
GIT_HASH=
# Options: prod, preprod, dev:
MATH_ENV=prod
# Options: debug, info, warn, error, fatal. Default is warn.
MATH_LOG_LEVEL=
# Optionally give the server container a distinct env_file. Useful for CI tests.
SERVER_ENV_FILE=.env
# Used by winston via server/utils/logger. Defaults to "info".
Expand Down
25 changes: 24 additions & 1 deletion math/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ If you're not familiar with Clojure and want a fun crash course, I highly recomm
If you're not using the docker compose infrastructure, you can run `clj -M:dev` to get nREPL going, but this will not start math worker's processing queue (or obviously any other parts of the system).
This may be preferable if you don't need the whole system running for whatever task you're working on.
You can always manually start the polling system by manually running `(runner/run!)`, as described below, as long as you have the `DATABASE_URL` environment variable pointing to a database (see [`doc/configuration.md`](doc/configuration.md))

## Starting and stopping the system

This application uses Stuart Sierra's Component library for REPL-reloadability.
Expand Down Expand Up @@ -80,12 +81,34 @@ We need to have a way of queueing up vote and moderation data updates, so that t

You can see the conversation manager implementation at [`src/polismath/conv_man.clj`](src/polismath/conv_man.clj).

## Logging Configuration

The system's logging level defaults to `:warn` but can be configured in several ways:

1. Set the `LOGGING_LEVEL` environment variable to change from the default `:warn` level:

```bash
MATH_LOG_LEVEL=info docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile postgres up
```

2. Modify the logging level in `resources/config.edn`
3. Set the level at runtime via the REPL:

```clojure
(require '[taoensso.timbre :as timbre])
(timbre/set-level! :info) ; Example of setting to a more verbose level
```

Available log levels (from lowest to highest): `:trace`, `:debug`, `:info`, `:warn`, `:error`, `:fatal`, `:report`

## Production setup

The [`docker-compose.yml`](../docker-compose.yml) file in the root of this directory, while not yet production ready, and still containing some development time artifacts, is provided as a basis for production deployment.
The [`docker-compose.yml`](../docker-compose.yml) file in the root of this directory is provided as a basis for production deployment.
Outstanding issues which need to be resolved before it would be ready include ensuring only necessary ports are exposed, etc.
The individual `Dockerfile`s that make up this infrastructure can currently be used by themselves, separate from `docker compose`, for deployment.

## Requirements

Nonetheless, if you wish to run this part of the system directly on a machine (outside of docker), the only requirements are that you:

* [install Clojure](https://clojure.org/guides/getting_started).
Expand Down
2 changes: 1 addition & 1 deletion math/resources/config.edn
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
;:group-k-buffer 4}}

:logging {:file "log/dev.log"
:level :info}
:level :warn}

;:math-env {:parse ->keyword}
;; Have to use :port since that's what heroku expects...
Expand Down
2 changes: 1 addition & 1 deletion math/src/polismath/components/config.clj
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
:poll-from-days-ago 10}
:math {:matrix-implementation :vectorz}
:logging {:file "log/dev.log"
:level :info}})
:level :warn}})

(defn ->long-list [x]
(when x
Expand Down
22 changes: 11 additions & 11 deletions math/src/polismath/components/logger.clj
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@
(defrecord Logger [config]
component/Lifecycle
(start [component]
(log/info ">> Starting config component")
;; Set minimum level first before any other logging happens
(when-let [level (get-in config [:logging :level])]
(log/set-level! level))
;; First merge the logging config from system config
(log/merge-config!
{;:middleware [] ; (fns [data]) -> ?data, applied left->right
;:timestamp-opts default-timestamp-opts ; {:pattern _ :locale _ :timezone _}
;:output-fn default-output-fn ; (fn [data]) -> string
:appenders {:println-appender
(:logging config))
;; Then merge appender config, inheriting the min-level from system config
(log/merge-config!
{:appenders {:println-appender
{:enabled? true
:async? false
:min-level nil
:min-level (get-in config [:logging :level] :warn) ; Use system config level or default to :warn
:rate-limit [[1 250] [10 5000]] ; 1/250ms, 10/5s
:output-fn :inherit
:fn ; Appender's fn
Expand All @@ -28,14 +31,11 @@
formatted-output-str (output-fn data)]
(println formatted-output-str)))}
:file-appender
{:spit (appenders/spit-appender {:fname "dev.log"})}}})
(log/merge-config!
(:logging config)))
{:spit (appenders/spit-appender {:fname (get-in config [:logging :file] "dev.log")})}}})
component)
(stop [component]
(log/info "<< Stopping config component")
component))

(defn create-logger []
(map->Logger {}))


12 changes: 6 additions & 6 deletions math/src/polismath/system.clj
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@
"This constructs an instance of the base system components, including config, db, etc."
[config-overrides]
{:config (config/create-config config-overrides)
;:logger (component/using (logger/create-logger) [:config])
:core-matrix-boot (component/using (core-matrix-boot/create-core-matrix-booter) [:config])
:postgres (component/using (postgres/create-postgres) [:config])
:conversation-manager (component/using (conv-man/create-conversation-manager) [:config :core-matrix-boot :postgres])})
:logger (component/using (logger/create-logger) [:config])
:core-matrix-boot (component/using (core-matrix-boot/create-core-matrix-booter) [:config :logger])
:postgres (component/using (postgres/create-postgres) [:config :logger])
:conversation-manager (component/using (conv-man/create-conversation-manager) [:config :core-matrix-boot :postgres :logger])})

(defn poller-system
"Creates a base-system and assocs in darwin server related components."
[config-overrides]
(merge
(base-system config-overrides)
{:vote-poller (component/using (poller/create-poller :votes) [:config :postgres :conversation-manager])
:mod-poller (component/using (poller/create-poller :moderation) [:config :postgres :conversation-manager])}))
{:vote-poller (component/using (poller/create-poller :votes) [:config :postgres :conversation-manager :logger])
:mod-poller (component/using (poller/create-poller :moderation) [:config :postgres :conversation-manager :logger])}))

(defn task-system
[config-overrides]
Expand Down

0 comments on commit f0454cd

Please sign in to comment.