mirror of
https://github.com/fleetbase/fleetbase.git
synced 2025-12-19 22:27:22 +00:00
Compare commits
5 Commits
a5a5ddb0d5
...
e41cd62ea5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e41cd62ea5 | ||
|
|
1ca1342052 | ||
|
|
a9b172081a | ||
|
|
a29ca0ecb9 | ||
|
|
6442644438 |
13
Caddyfile
13
Caddyfile
@@ -1,9 +1,6 @@
|
|||||||
{
|
{
|
||||||
frankenphp {
|
frankenphp {
|
||||||
# Reduced from 24 to 20 for better resource management
|
num_threads 24
|
||||||
# With 4 containers: 20 × 4 = 80 total workers
|
|
||||||
# Requires db.t3.large (591 max connections) or better
|
|
||||||
num_threads 20
|
|
||||||
}
|
}
|
||||||
order php_server before file_server
|
order php_server before file_server
|
||||||
}
|
}
|
||||||
@@ -12,14 +9,6 @@ http://:8000 {
|
|||||||
root * /fleetbase/api/public
|
root * /fleetbase/api/public
|
||||||
encode zstd br gzip
|
encode zstd br gzip
|
||||||
|
|
||||||
# Request timeouts to prevent hanging
|
|
||||||
timeouts {
|
|
||||||
read_body 10s
|
|
||||||
read_header 5s
|
|
||||||
write 60s
|
|
||||||
idle 120s
|
|
||||||
}
|
|
||||||
|
|
||||||
php_server {
|
php_server {
|
||||||
resolve_root_symlink
|
resolve_root_symlink
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ return [
|
|||||||
OperationTerminated::class => [
|
OperationTerminated::class => [
|
||||||
FlushOnce::class,
|
FlushOnce::class,
|
||||||
FlushTemporaryContainerInstances::class,
|
FlushTemporaryContainerInstances::class,
|
||||||
DisconnectFromDatabases::class, // ✅ Release DB connections after each request
|
DisconnectFromDatabases::class,
|
||||||
CollectGarbage::class, // ✅ Prevent memory leaks
|
CollectGarbage::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
WorkerErrorOccurred::class => [
|
WorkerErrorOccurred::class => [
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Application from '@ember/application';
|
|||||||
import Resolver from 'ember-resolver';
|
import Resolver from 'ember-resolver';
|
||||||
import loadInitializers from 'ember-load-initializers';
|
import loadInitializers from 'ember-load-initializers';
|
||||||
import config from '@fleetbase/console/config/environment';
|
import config from '@fleetbase/console/config/environment';
|
||||||
|
import './deprecation-workflow';
|
||||||
|
|
||||||
export default class App extends Application {
|
export default class App extends Application {
|
||||||
modulePrefix = config.modulePrefix;
|
modulePrefix = config.modulePrefix;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<section class="onboarding step-host">
|
<section class="onboarding step-host">
|
||||||
{{#if this.initialized}}
|
{{#if this.initialized}}
|
||||||
{{#if this.currentComponent}}
|
{{#if this.orchestrator.wrapper}}
|
||||||
{{component this.currentComponent context=this.context orchestrator=this.orchestrator brand=@brand}}
|
{{component (lazy-engine-component this.orchestrator.wrapper) currentStepComponent=this.currentComponent context=this.context orchestrator=this.orchestrator brand=@brand}}
|
||||||
|
{{else if this.currentComponent}}
|
||||||
|
{{component (lazy-engine-component this.currentComponent) context=this.context orchestrator=this.orchestrator brand=@brand}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="flex items-center justify-center min-h-24">
|
<div class="flex items-center justify-center min-h-24">
|
||||||
|
|||||||
9
console/app/deprecation-workflow.js
Normal file
9
console/app/deprecation-workflow.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import setupDeprecationWorkflow from 'ember-cli-deprecation-workflow';
|
||||||
|
|
||||||
|
setupDeprecationWorkflow({
|
||||||
|
workflow: [
|
||||||
|
{ handler: 'silence', matchId: 'ember-concurrency.deprecate-decorator-task' },
|
||||||
|
{ handler: 'silence', matchId: 'new-helper-names' },
|
||||||
|
{ handler: 'silence', matchId: 'ember-data:deprecate-non-strict-relationships' },
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -7,17 +7,31 @@ export default class OnboardingOrchestratorService extends Service {
|
|||||||
@service onboardingContext;
|
@service onboardingContext;
|
||||||
|
|
||||||
@tracked flow = null;
|
@tracked flow = null;
|
||||||
|
@tracked wrapper = null;
|
||||||
@tracked current = null;
|
@tracked current = null;
|
||||||
@tracked history = [];
|
@tracked history = [];
|
||||||
@tracked sessionId = null;
|
@tracked sessionId = null;
|
||||||
|
|
||||||
start(flowId = null, opts = {}) {
|
async start(flowId = null, opts = {}) {
|
||||||
const flow = this.onboardingRegistry.getFlow(flowId ?? this.onboardingRegistry.defaultFlow);
|
const flow = this.onboardingRegistry.getFlow(flowId ?? this.onboardingRegistry.defaultFlow);
|
||||||
if (!flow) throw new Error(`Onboarding flow '${flowId}' not found`);
|
if (!flow) throw new Error(`Onboarding flow '${flowId}' not found`);
|
||||||
|
|
||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
|
this.wrapper = flow.wrapper || null;
|
||||||
this.sessionId = opts.sessionId || null;
|
this.sessionId = opts.sessionId || null;
|
||||||
this.history = [];
|
this.history = [];
|
||||||
this.goto(flow.entry);
|
|
||||||
|
// Execute onFlowWillStart hook if defined
|
||||||
|
if (typeof this.flow.onFlowWillStart === 'function') {
|
||||||
|
await this.flow.onFlowWillStart(this.flow, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.goto(flow.entry);
|
||||||
|
|
||||||
|
// Execute onFlowDidStart hook if defined
|
||||||
|
if (typeof this.flow.onFlowDidStart === 'function') {
|
||||||
|
await this.flow.onFlowDidStart(this.flow, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async goto(stepId) {
|
async goto(stepId) {
|
||||||
@@ -25,27 +39,43 @@ export default class OnboardingOrchestratorService extends Service {
|
|||||||
const step = this.flow.steps.find((s) => s.id === stepId);
|
const step = this.flow.steps.find((s) => s.id === stepId);
|
||||||
if (!step) throw new Error(`Step '${stepId}' not found`);
|
if (!step) throw new Error(`Step '${stepId}' not found`);
|
||||||
|
|
||||||
|
// Execute onStepWillChange hook if defined
|
||||||
|
const previousStep = this.current;
|
||||||
|
if (typeof this.flow.onStepWillChange === 'function') {
|
||||||
|
await this.flow.onStepWillChange(step, previousStep, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guard function - skip step if guard returns false
|
||||||
if (typeof step.guard === 'function' && !step.guard(this.onboardingContext)) {
|
if (typeof step.guard === 'function' && !step.guard(this.onboardingContext)) {
|
||||||
return this.next();
|
return this.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// beforeEnter lifecycle hook
|
||||||
if (typeof step.beforeEnter === 'function') {
|
if (typeof step.beforeEnter === 'function') {
|
||||||
await step.beforeEnter(this.onboardingContext);
|
await step.beforeEnter(this.onboardingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.current = step;
|
this.current = step;
|
||||||
|
|
||||||
|
// Execute onStepDidChange hook if defined
|
||||||
|
if (typeof this.flow.onStepDidChange === 'function') {
|
||||||
|
await this.flow.onStepDidChange(this.current, previousStep, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async next() {
|
async next() {
|
||||||
if (!this.flow || !this.current) return;
|
if (!this.flow || !this.current) return;
|
||||||
|
|
||||||
const leaving = this.current;
|
const leaving = this.current;
|
||||||
|
|
||||||
|
// afterLeave lifecycle hook
|
||||||
if (typeof leaving.afterLeave === 'function') {
|
if (typeof leaving.afterLeave === 'function') {
|
||||||
await leaving.afterLeave(this.onboardingContext);
|
await leaving.afterLeave(this.onboardingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.history.includes(leaving)) this.history.push(leaving);
|
if (!this.history.includes(leaving)) this.history.push(leaving);
|
||||||
|
|
||||||
|
// Support both string and function for next property
|
||||||
let nextId;
|
let nextId;
|
||||||
if (typeof leaving.next === 'function') {
|
if (typeof leaving.next === 'function') {
|
||||||
nextId = leaving.next(this.onboardingContext);
|
nextId = leaving.next(this.onboardingContext);
|
||||||
@@ -53,8 +83,20 @@ export default class OnboardingOrchestratorService extends Service {
|
|||||||
nextId = leaving.next;
|
nextId = leaving.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no next step, flow is complete
|
||||||
if (!nextId) {
|
if (!nextId) {
|
||||||
|
// Execute onFlowWillEnd hook if defined
|
||||||
|
if (typeof this.flow.onFlowWillEnd === 'function') {
|
||||||
|
await this.flow.onFlowWillEnd(leaving, this);
|
||||||
|
}
|
||||||
|
|
||||||
this.current = null; // finished
|
this.current = null; // finished
|
||||||
|
|
||||||
|
// Execute onFlowDidEnd hook if defined
|
||||||
|
if (typeof this.flow.onFlowDidEnd === 'function') {
|
||||||
|
await this.flow.onFlowDidEnd(leaving, this);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,4 +110,31 @@ export default class OnboardingOrchestratorService extends Service {
|
|||||||
this.history = this.history.slice(0, -1);
|
this.history = this.history.slice(0, -1);
|
||||||
await this.goto(prev.id);
|
await this.goto(prev.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current path (for flows with multiple paths)
|
||||||
|
* This is a helper method that can be used by flows to determine the current path
|
||||||
|
*/
|
||||||
|
getCurrentPath() {
|
||||||
|
if (!this.flow || !this.flow.paths) return null;
|
||||||
|
|
||||||
|
// Determine path based on context or current step
|
||||||
|
for (const [pathId, pathDef] of Object.entries(this.flow.paths)) {
|
||||||
|
if (pathDef.steps && pathDef.steps.some(s => s.id === this.current?.id)) {
|
||||||
|
return pathDef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a step is in the current path
|
||||||
|
*/
|
||||||
|
isStepInPath(stepId) {
|
||||||
|
const currentPath = this.getCurrentPath();
|
||||||
|
if (!currentPath) return true; // If no paths defined, all steps are valid
|
||||||
|
|
||||||
|
return currentPath.steps?.some(s => s.id === stepId) ?? false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default class OnboardingRegistryService extends Service {
|
|||||||
this.defaultFlow = flowId;
|
this.defaultFlow = flowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerFlow(flow) {
|
registerFlow(flow, options = {}) {
|
||||||
if (!flow || !flow.id || !flow.entry || !Array.isArray(flow.steps)) {
|
if (!flow || !flow.id || !flow.entry || !Array.isArray(flow.steps)) {
|
||||||
throw new Error('Invalid FlowDef: id, entry, steps are required');
|
throw new Error('Invalid FlowDef: id, entry, steps are required');
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,11 @@ export default class OnboardingRegistryService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.flows.set(flow.id, flow);
|
this.flows.set(flow.id, flow);
|
||||||
|
|
||||||
|
// If specified, set as default flow
|
||||||
|
if (options.default) {
|
||||||
|
this.defaultFlow = flow.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getFlow(id) {
|
getFlow(id) {
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
<div class="flex items-center justify-center h-screen min-h-screen px-4 py-12 bg-gray-50 dark:bg-gray-900 sm:px-6 lg:px-8 overflow-y-scroll">
|
<div class="onboard-route-wrapper">
|
||||||
<div class="w-full max-w-md h-screen flex items-center justify-center py-4">
|
{{outlet}}
|
||||||
{{outlet}}
|
|
||||||
</div>
|
|
||||||
<Spacer @height="300px" />
|
|
||||||
</div>
|
</div>
|
||||||
@@ -23,7 +23,7 @@ module.exports = function (environment) {
|
|||||||
APP: {
|
APP: {
|
||||||
autoboot: true,
|
autoboot: true,
|
||||||
extensions: asArray(getenv('EXTENSIONS')),
|
extensions: asArray(getenv('EXTENSIONS')),
|
||||||
disableRuntimeConfig: toBoolean(getenv('DISABLE_RUNTIME_CONFIG')),
|
disableRuntimeConfig: toBoolean(getenv('DISABLE_RUNTIME_CONFIG', environment === 'production')),
|
||||||
},
|
},
|
||||||
|
|
||||||
API: {
|
API: {
|
||||||
|
|||||||
@@ -158,14 +158,14 @@ CMD ["php", "artisan", "queue:work"]
|
|||||||
# Application dev stage
|
# Application dev stage
|
||||||
FROM base AS app-dev
|
FROM base AS app-dev
|
||||||
ENTRYPOINT ["docker-php-entrypoint"]
|
ENTRYPOINT ["docker-php-entrypoint"]
|
||||||
CMD ["sh", "-c", "php artisan octane:frankenphp --workers=20 --max-requests=1000 --port=8000 --host=0.0.0.0 --watch"]
|
CMD ["sh", "-c", "php artisan octane:frankenphp --max-requests=1000 --port=8000 --host=0.0.0.0 --watch"]
|
||||||
|
|
||||||
# Application release stage
|
# Application release stage
|
||||||
FROM base AS app-release
|
FROM base AS app-release
|
||||||
ENTRYPOINT ["docker-php-entrypoint"]
|
ENTRYPOINT ["docker-php-entrypoint"]
|
||||||
CMD ["sh", "-c", "php artisan octane:frankenphp --workers=20 --max-requests=1000 --port=8000 --host=0.0.0.0"]
|
CMD ["sh", "-c", "php artisan octane:frankenphp --max-requests=1000 --port=8000 --host=0.0.0.0"]
|
||||||
|
|
||||||
# Application stage
|
# Application stage
|
||||||
FROM base AS app
|
FROM base AS app
|
||||||
ENTRYPOINT ["/sbin/ssm-parent", "-c", ".ssm-parent.yaml", "run", "--", "docker-php-entrypoint"]
|
ENTRYPOINT ["/sbin/ssm-parent", "-c", ".ssm-parent.yaml", "run", "--", "docker-php-entrypoint"]
|
||||||
CMD ["sh", "-c", "php artisan octane:frankenphp --workers=20 --max-requests=1000 --port=8000 --host=0.0.0.0"]
|
CMD ["sh", "-c", "php artisan octane:frankenphp --max-requests=1000 --port=8000 --host=0.0.0.0"]
|
||||||
|
|||||||
Reference in New Issue
Block a user