Skip to content

Commit 4fe76fd

Browse files
Merge pull request #2514 from FarmBot/staging
v15.24.1
2 parents 4d972e0 + 0f0ac54 commit 4fe76fd

9 files changed

Lines changed: 114 additions & 63 deletions

File tree

Procfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
worker: bundle exec rake jobs:work
22
rabbit_workers: bin/rails r lib/rabbit_workers.rb
3-
web: bundle exec passenger start -p $PORT -e $RAILS_ENV --max-pool-size $MAX_POOL_SIZE
3+
web: bundle exec passenger start -p $PORT -e $RAILS_ENV --max-pool-size ${MAX_POOL_SIZE:-1} --max-requests ${MAX_REQUESTS:-1000}
44
# This will perform a hard refresh on all connected browsers.
55
release: rails r "User.refresh_everyones_ui" && rails db:migrate && (bundle exec rake hook:release_info || true)

app/models/device.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,19 @@ def trim_excess_telemetry
124124
# Give the user back the amount of sensor readings they are allowed to view.
125125
def limited_sensor_readings_list
126126
sensor_readings
127-
.order(created_at: :desc)
127+
.order(created_at: :desc, id: :desc)
128128
.limit(DEFAULT_MAX_SENSOR_READINGS)
129129
end
130130

131131
def excess_sensor_readings
132+
sensor_readings.where(id: excess_sensor_reading_ids_subquery)
133+
end
134+
135+
def excess_sensor_reading_ids_subquery
132136
sensor_readings
133-
.where
134-
.not(id: limited_sensor_readings_list.pluck(:id))
135-
.where(device_id: self.id)
137+
.order(created_at: :desc, id: :desc)
138+
.offset(DEFAULT_MAX_SENSOR_READINGS)
139+
.select(:id)
136140
end
137141

138142
def trim_excess_sensor_readings

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ services:
5050
build:
5151
context: "."
5252
dockerfile: docker_configs/api.Dockerfile
53-
command: bash -c "rm -f tmp/pids/server.pid && bundle exec passenger start"
53+
command: bash -c "rm -f tmp/pids/server.pid && bundle exec passenger start --max-pool-size ${MAX_POOL_SIZE:-1} --max-requests ${MAX_REQUESTS:-1000}"
5454
ports: ["${API_PORT}:${API_PORT}"]
5555

5656
mqtt:

example.env

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,12 @@ CODECOV_TOKEN=
142142

143143
# Set the max pool size for Passenger. (Only needed if using Heroku)
144144
# FarmBot Inc uses Heroku. Self hosters do not.
145-
MAX_POOL_SIZE=2
145+
MAX_POOL_SIZE=1
146+
147+
# Set the max number of requests until restart for Passenger.
148+
# (Only needed if using Heroku)
149+
# FarmBot Inc uses Heroku. Self hosters do not.
150+
MAX_REQUESTS=1000
146151

147152
# This is set by Heroku and used by the frontend to show the current version.
148153
# Most self hosting users will want to delete this.

frontend/css/panels/sequences.scss

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,18 @@
3636
}
3737
.panel-content {
3838
.sequence-editor-content {
39-
overflow: hidden;
39+
overflow-x: hidden;
40+
overflow-y: visible;
4041

4142
@media screen and (max-width: 767px) {
4243
margin-left: 5px;
4344
padding-right: 0;
4445
}
4546
}
4647
.add-command-button-container {
47-
display: block;
48-
height: 0;
49-
.bp6-collapse {
50-
padding: 0;
51-
}
52-
.bp6-collapse-body {
53-
padding: 0;
54-
}
48+
align-items: start;
49+
justify-content: right;
50+
grid-template-columns: 1fr auto;
5551
}
5652
.drag-drop-area {
5753
display: none;
@@ -258,7 +254,6 @@
258254

259255
.sequence-editor-sections {
260256
.bp6-collapse {
261-
padding: 0 1rem;
262257
.bp6-collapse-body {
263258
padding-bottom: 1rem;
264259
}
@@ -551,8 +546,11 @@
551546
}
552547
}
553548

549+
.sequence-step-components {
550+
padding: 0 1rem;
551+
}
552+
554553
.sequence-steps {
555-
margin-right: 2.5rem;
556554
.sequence-step {
557555
&.hovered {
558556
box-shadow: 0px 0px 15px #f70;
@@ -571,10 +569,20 @@
571569
}
572570
}
573571

572+
.sequence-steps > .step-dragger {
573+
margin-right: 2.5rem;
574+
}
575+
576+
.sequence-page {
577+
.step-dragger {
578+
margin-right: 0;
579+
}
580+
.add-command-button-container {
581+
display: none;
582+
}
583+
}
584+
574585
.step-button-cluster {
575-
overflow-y: auto;
576-
overflow-x: hidden;
577-
max-height: calc(100vh - 8rem);
578586
.text-input-wrapper {
579587
input {
580588
padding: 0;
@@ -607,7 +615,6 @@
607615
&.designer-cluster {
608616
margin: 0;
609617
background: $dark_gray;
610-
margin-bottom: 1rem;
611618
border-radius: 5px;
612619
overflow: unset;
613620
padding: 0.75rem;
@@ -1087,11 +1094,9 @@
10871094
}
10881095

10891096
.add-command-button-container {
1090-
display: none;
1091-
position: absolute;
1092-
z-index: 9;
1093-
width: 100%;
1094-
height: 0;
1097+
.bp6-collapse {
1098+
transition-duration: 0ms !important;
1099+
}
10951100
button {
10961101
margin: 0;
10971102
}
@@ -1103,6 +1108,8 @@
11031108
height: 20px;
11041109
padding: 0.25rem;
11051110
border-radius: 2rem;
1111+
margin-bottom: -.75rem;
1112+
right: -2.5rem;
11061113
box-shadow: none !important;
11071114
background: $dark_gray !important;
11081115
i {
@@ -1130,7 +1137,6 @@
11301137
&.last {
11311138
.bp6-collapse {
11321139
margin-top: 1rem;
1133-
margin-right: 2.5rem;
11341140
}
11351141
.add-command {
11361142
margin-top: -2rem;
@@ -1145,29 +1151,15 @@
11451151
}
11461152
}
11471153
&.only {
1148-
position: relative;
1149-
margin: auto;
1150-
text-align: center;
1151-
height: 3rem;
11521154
.add-command {
11531155
display: none;
11541156
}
11551157
.step-button-cluster {
11561158
margin: 0;
11571159
}
11581160
}
1159-
1160-
@media screen and (max-width: 767px) {
1161-
display: block;
1162-
.add-command {
1163-
display: block;
1164-
}
1165-
}
11661161
&.open {
1167-
position: relative;
11681162
.add-command {
1169-
position: absolute;
1170-
right: -2.5rem;
11711163
transform: rotate(-45deg);
11721164
i {
11731165
transform: rotate(0);

frontend/sequences/__tests__/sequence_editor_middle_active_test.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
SequenceBtnGroup,
99
SequenceShareMenu,
1010
SequencePublishMenu,
11+
AddCommandButton,
1112
isSequencePublished,
1213
AddCommandButtonProps,
1314
} from "../sequence_editor_middle_active";
@@ -835,11 +836,6 @@ describe("<AddCommandButton />", () => {
835836
stepButtonClusterSpy.mockRestore();
836837
});
837838

838-
const getAddCommandButton = async () => {
839-
return (await import(`../sequence_editor_middle_active.tsx?m=${Math.random()}`))
840-
.AddCommandButton;
841-
};
842-
843839
const fakeProps = (): AddCommandButtonProps => ({
844840
dispatch: jest.fn(),
845841
index: 1,
@@ -850,10 +846,9 @@ describe("<AddCommandButton />", () => {
850846
resources: buildResourceIndex().index,
851847
});
852848

853-
it("dispatches new step position", async () => {
849+
it("dispatches new step position", () => {
854850
location.pathname = "";
855851
const p = fakeProps();
856-
const AddCommandButton = await getAddCommandButton();
857852
const wrapper = createRenderer(<AddCommandButton {...p} />);
858853
const button = wrapper.root.findAll(node =>
859854
typeof node.props.onClick == "function" &&
@@ -876,12 +871,13 @@ describe("<AddCommandButton />", () => {
876871
unmountRenderer(wrapper);
877872
});
878873

879-
it("closes cluster", async () => {
880-
const AddCommandButton = await getAddCommandButton();
874+
it("closes cluster", () => {
881875
const { container } = render(<AddCommandButton {...fakeProps()} />);
882876
const cluster = container.querySelector(".add-command-button-container");
883877
const close = container.querySelector(".step-button-cluster-close");
884878
if (cluster && close) {
879+
expect(cluster.classList.contains("row")).toBeTruthy();
880+
expect(cluster.classList.contains("half-gap")).toBeTruthy();
885881
expect(cluster.classList.contains("open")).toBeTruthy();
886882
fireEvent.click(close);
887883
expect(cluster.classList.contains("open")).toBeFalsy();

frontend/sequences/all_steps.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ export class AllSteps extends React.Component<AllStepsProps, {}> {
5555
const hovered = this.props.visualized && this.props.hoveredStep === tag
5656
? "hovered"
5757
: "";
58-
return <div className="sequence-steps"
58+
return <div className="sequence-steps grid no-gap"
5959
key={readThatCommentAbove}>
60+
<DropArea callback={key => this.props.onDrop(index, key)} />
6061
{!this.props.readOnly &&
6162
<AddCommandButton dispatch={dispatch} index={index} stepCount={1}
6263
sequence={this.props.sequence}
6364
farmwareData={this.props.farmwareData}
6465
sequences={this.props.sequences}
6566
resources={this.props.resources} />}
66-
<DropArea callback={key => this.props.onDrop(index, key)} />
6767
<StepDragger
6868
dispatch={dispatch}
6969
step={currentStep}

frontend/sequences/sequence_editor_middle_active.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,19 @@ export const AddCommandButton = (props: AddCommandButtonProps) => {
849849
"add-command-button-container",
850850
getPositionClass(),
851851
collapsed ? "" : "open",
852+
"row",
853+
"half-gap",
852854
].join(" ")}>
855+
<Collapse isOpen={!collapsed}>
856+
<StepButtonCluster
857+
close={() => setCollapsed(true)}
858+
current={props.sequence}
859+
dispatch={dispatch}
860+
farmwareData={props.farmwareData}
861+
sequences={props.sequences}
862+
resources={props.resources}
863+
stepIndex={index} />
864+
</Collapse>
853865
<button
854866
className={"add-command fb-button gray"}
855867
title={t("add sequence step")}
@@ -862,16 +874,6 @@ export const AddCommandButton = (props: AddCommandButtonProps) => {
862874
}}>
863875
<i className={"fa fa-plus"} />
864876
</button>
865-
<Collapse isOpen={!collapsed}>
866-
<StepButtonCluster
867-
close={() => setCollapsed(true)}
868-
current={props.sequence}
869-
dispatch={dispatch}
870-
farmwareData={props.farmwareData}
871-
sequences={props.sequences}
872-
resources={props.resources}
873-
stepIndex={index} />
874-
</Collapse>
875877
</div>;
876878
};
877879

spec/models/device_spec.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,58 @@
117117
device.send_upgrade_request
118118
end
119119

120+
it "builds a DB-only subquery for excess sensor readings" do
121+
relation = device.excess_sensor_readings
122+
123+
expect(relation.to_sql).to include("OFFSET #{Device::DEFAULT_MAX_SENSOR_READINGS}")
124+
expect(relation.to_sql).to include("\"sensor_readings\".\"id\" IN")
125+
end
126+
127+
it "returns limited sensor readings in reverse chronological order" do
128+
const_reassign(Device, :DEFAULT_MAX_SENSOR_READINGS, 2) do
129+
oldest = FactoryBot.create(:sensor_reading,
130+
device: device,
131+
created_at: 2.seconds.ago,
132+
updated_at: 2.seconds.ago)
133+
tied_time = 1.second.ago
134+
older_tied = FactoryBot.create(:sensor_reading,
135+
device: device,
136+
created_at: tied_time,
137+
updated_at: tied_time)
138+
newer_tied = FactoryBot.create(:sensor_reading,
139+
device: device,
140+
created_at: tied_time,
141+
updated_at: tied_time)
142+
143+
expect(device.limited_sensor_readings_list.pluck(:id))
144+
.to eq([newer_tied.id, older_tied.id])
145+
expect(device.limited_sensor_readings_list.pluck(:id))
146+
.not_to include(oldest.id)
147+
end
148+
end
149+
150+
it "trims older sensor readings beyond the device limit" do
151+
const_reassign(Device, :DEFAULT_MAX_SENSOR_READINGS, 2) do
152+
oldest = FactoryBot.create(:sensor_reading,
153+
device: device,
154+
created_at: 3.seconds.ago,
155+
updated_at: 3.seconds.ago)
156+
middle = FactoryBot.create(:sensor_reading,
157+
device: device,
158+
created_at: 2.seconds.ago,
159+
updated_at: 2.seconds.ago)
160+
newest = FactoryBot.create(:sensor_reading,
161+
device: device,
162+
created_at: 1.second.ago,
163+
updated_at: 1.second.ago)
164+
165+
device.trim_excess_sensor_readings
166+
167+
expect(device.sensor_readings.pluck(:id)).to match_array([middle.id, newest.id])
168+
expect(SensorReading.exists?(oldest.id)).to be(false)
169+
end
170+
end
171+
120172
it "reports unknown location in feedback payload when coordinates are missing" do
121173
expect(Faraday).to receive(:post) do |_url, payload, _headers|
122174
text = JSON.parse(payload)["text"]

0 commit comments

Comments
 (0)