From 9f60fc6255000d659d38b35cc76190a86869b85a Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Wed, 26 Nov 2025 13:43:55 +0100 Subject: [PATCH 1/5] Fix error logging --- app/grpc/data_type_handler.rb | 3 --- app/services/error_code.rb | 1 + .../runtimes/data_types/update_service.rb | 18 ++++++++++++++---- .../runtimes/flow_types/update_service.rb | 19 +++++++++++++++---- .../update_service.rb | 17 +++++++++++++---- docs/graphql/enum/errorcodeenum.md | 1 + 6 files changed, 44 insertions(+), 15 deletions(-) diff --git a/app/grpc/data_type_handler.rb b/app/grpc/data_type_handler.rb index 1d15703c..2b2e7e77 100644 --- a/app/grpc/data_type_handler.rb +++ b/app/grpc/data_type_handler.rb @@ -2,15 +2,12 @@ class DataTypeHandler < Tucana::Sagittarius::DataTypeService::Service include GrpcHandler - include Code0::ZeroTrack::Loggable def update(request, _call) current_runtime = Runtime.find(Code0::ZeroTrack::Context.current[:runtime][:id]) response = Runtimes::DataTypes::UpdateService.new(current_runtime, request.data_types).execute - logger.info(message: 'Data types updated', runtime_id: current_runtime.id, response: response.to_h) - Tucana::Sagittarius::DataTypeUpdateResponse.new(success: response.success?) end end diff --git a/app/services/error_code.rb b/app/services/error_code.rb index 0630c4a7..a57b0ab7 100644 --- a/app/services/error_code.rb +++ b/app/services/error_code.rb @@ -80,6 +80,7 @@ def self.error_codes no_datatype_identifier_for_generic_key: { description: 'No data type identifier could be found for the given generic key' }, invalid_generic_mapper: { description: 'The generic mapper is invalid because of active model errors' }, invalid_data_type: { description: 'The data type is invalid because of active model errors' }, + invalid_flow_type: { description: 'The flow type is invalid because of active model errors' }, primary_level_not_found: { description: '', deprecation_reason: 'Outdated concept' }, secondary_level_not_found: { description: '', deprecation_reason: 'Outdated concept' }, diff --git a/app/services/runtimes/data_types/update_service.rb b/app/services/runtimes/data_types/update_service.rb index 823aca57..ec836d8c 100644 --- a/app/services/runtimes/data_types/update_service.rb +++ b/app/services/runtimes/data_types/update_service.rb @@ -4,6 +4,7 @@ module Runtimes module DataTypes class UpdateService include Sagittarius::Database::Transactional + include Code0::ZeroTrack::Loggable attr_reader :current_runtime, :data_types @@ -18,14 +19,22 @@ def execute DataType.where(runtime: current_runtime).update_all(removed_at: Time.zone.now) # rubocop:enable Rails/SkipsModelValidations sort_data_types(data_types).each do |data_type| - unless update_datatype(data_type, t) - t.rollback_and_return! ServiceResponse.error(message: 'Failed to update data type', - error_code: :invalid_data_type, details: data_type.errors) - end + db_data_type = update_datatype(data_type, t) + next if db_data_type.persisted? + + logger.error(message: 'Failed to update data type', + runtime_id: current_runtime.id, + data_type_identifier: data_type.identifier, + errors: db_data_type.errors.full_messages) + + t.rollback_and_return! ServiceResponse.error(message: 'Failed to update data type', + error_code: :invalid_data_type, details: db_data_type.errors) end UpdateRuntimeCompatibilityJob.perform_later({ runtime_id: current_runtime.id }) + logger.info(message: 'Updated data types for runtime', runtime_id: current_runtime.id) + ServiceResponse.success(message: 'Updated data types', payload: data_types) end end @@ -80,6 +89,7 @@ def update_datatype(data_type, t) db_object.generic_keys = data_type.generic_keys.to_a db_object.version = "#{data_type.version.major}.#{data_type.version.minor}.#{data_type.version.patch}" db_object.save + db_object end def find_data_type_identifier(parent_type_rule_config, t) diff --git a/app/services/runtimes/flow_types/update_service.rb b/app/services/runtimes/flow_types/update_service.rb index 093ddbf1..13e2674f 100644 --- a/app/services/runtimes/flow_types/update_service.rb +++ b/app/services/runtimes/flow_types/update_service.rb @@ -4,6 +4,7 @@ module Runtimes module FlowTypes class UpdateService include Sagittarius::Database::Transactional + include Code0::ZeroTrack::Loggable attr_reader :current_runtime, :flow_types @@ -18,10 +19,19 @@ def execute FlowType.where(runtime: current_runtime).update_all(removed_at: Time.zone.now) # rubocop:enable Rails/SkipsModelValidations flow_types.each do |flow_type| - unless update_flowtype(flow_type, t) - t.rollback_and_return! ServiceResponse.error(message: 'Failed to update flow type', - payload: flow_type.errors) - end + db_flow_type = update_flowtype(flow_type, t) + next if db_flow_type.persisted? + + logger.error( + message: 'Failed to update flow type', + runtime_id: current_runtime.id, + flow_type_identifier: flow_type.identifier, + errors: db_flow_type.errors.full_messages + ) + + t.rollback_and_return! ServiceResponse.error(message: 'Failed to update flow type', + error_code: :invalid_flow_type, + details: db_flow_type.errors) end UpdateRuntimeCompatibilityJob.perform_later({ runtime_id: current_runtime.id }) @@ -49,6 +59,7 @@ def update_flowtype(flow_type, t) db_object.aliases = update_translations(flow_type.alias, db_object.aliases) db_object.version = "#{flow_type.version.major}.#{flow_type.version.minor}.#{flow_type.version.patch}" db_object.save + db_object end def find_datatype(identifier, t) diff --git a/app/services/runtimes/runtime_function_definitions/update_service.rb b/app/services/runtimes/runtime_function_definitions/update_service.rb index bdccdc3d..8611b4c8 100644 --- a/app/services/runtimes/runtime_function_definitions/update_service.rb +++ b/app/services/runtimes/runtime_function_definitions/update_service.rb @@ -4,6 +4,7 @@ module Runtimes module RuntimeFunctionDefinitions class UpdateService include Sagittarius::Database::Transactional + include Code0::ZeroTrack::Loggable attr_reader :current_runtime, :runtime_function_definitions @@ -19,14 +20,22 @@ def execute # rubocop:enable Rails/SkipsModelValidations runtime_function_definitions.each do |runtime_function_definition| response = update_runtime_function_definition(runtime_function_definition, t) - unless response.persisted? - t.rollback_and_return! ServiceResponse.error(message: 'Failed to update runtime function definition', - payload: response.errors) - end + next if response.persisted? + + logger.error(message: 'Failed to update runtime function definition', + runtime_id: current_runtime.id, + definition_identifier: runtime_function_definition.identifier, + errors: response.errors.full_messages) + + t.rollback_and_return! ServiceResponse.error(message: 'Failed to update runtime function definition', + error_code: :invalid_runtime_function_definition, + details: response.errors) end UpdateRuntimeCompatibilityJob.perform_later({ runtime_id: current_runtime.id }) + logger.info(message: 'Updated runtime function definitions for runtime', runtime_id: current_runtime.id) + ServiceResponse.success(message: 'Updated runtime function definition', payload: runtime_function_definitions) end end diff --git a/docs/graphql/enum/errorcodeenum.md b/docs/graphql/enum/errorcodeenum.md index 767ce4dc..b9e61031 100644 --- a/docs/graphql/enum/errorcodeenum.md +++ b/docs/graphql/enum/errorcodeenum.md @@ -28,6 +28,7 @@ Represents the available error responses | `INVALID_EXTERNAL_IDENTITY` | This external identity is invalid | | `INVALID_FLOW` | The flow is invalid because of active model errors | | `INVALID_FLOW_SETTING` | The flow setting is invalid because of active model errors | +| `INVALID_FLOW_TYPE` | The flow type is invalid because of active model errors | | `INVALID_GENERIC_MAPPER` | The generic mapper is invalid because of active model errors | | `INVALID_LOGIN_DATA` | Invalid login data provided | | `INVALID_NAMESPACE_LICENSE` | The namespace license is invalid because of active model errors | From b490a1c0d7cccfae95eceafa218b48fdc27dd9d3 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Wed, 26 Nov 2025 16:30:57 +0100 Subject: [PATCH 2/5] Fix wrong parsing of rules --- .../runtimes/data_types/update_service.rb | 20 ++++++++++++++++++- .../sagittarius/data_type_service_spec.rb | 9 ++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/services/runtimes/data_types/update_service.rb b/app/services/runtimes/data_types/update_service.rb index ec836d8c..8bb4058a 100644 --- a/app/services/runtimes/data_types/update_service.rb +++ b/app/services/runtimes/data_types/update_service.rb @@ -158,8 +158,26 @@ def find_data_type(identifier, t) def update_rules(rules, data_type) db_rules = data_type.rules.first(rules.length) rules.each_with_index do |rule, index| + config = rule.rule_config.to_h.transform_values do |value| + case value + when Tucana::Shared::DataTypeIdentifier + if value.data_type_identifier.present? + value.data_type_identifier + elsif value.generic_key.present? + { generic_key: value.generic_key } + else + { generic_type: value.generic_type } + end + else + value + end + end + db_rules[index] ||= DataTypeRule.new - db_rules[index].assign_attributes(variant: rule.variant.to_s.downcase, config: rule.rule_config.to_h) + db_rules[index].assign_attributes( + variant: rule.variant.to_s.downcase, + config: config + ) end db_rules diff --git a/spec/requests/grpc/sagittarius/data_type_service_spec.rb b/spec/requests/grpc/sagittarius/data_type_service_spec.rb index 4fdd956a..47416f37 100644 --- a/spec/requests/grpc/sagittarius/data_type_service_spec.rb +++ b/spec/requests/grpc/sagittarius/data_type_service_spec.rb @@ -23,7 +23,10 @@ { code: 'de_DE', content: 'Zahl: ${0}' } ], rules: [ - Tucana::Shared::DefinitionDataTypeRule.create(:number_range, { from: 1, to: 10 }) + Tucana::Shared::DefinitionDataTypeRule.create( + :contains_type, + { data_type_identifier: { generic_key: 'T' } } + ) ], version: { major: 0, @@ -58,8 +61,8 @@ expect(data_type.display_messages.first.code).to eq('de_DE') expect(data_type.display_messages.first.content).to eq('Zahl: ${0}') expect(data_type.rules.count).to eq(1) - expect(data_type.rules.first.variant).to eq('number_range') - expect(data_type.rules.first.config).to eq({ 'from' => 1, 'to' => 10, 'steps' => 0 }) + expect(data_type.rules.first.variant).to eq('contains_type') + expect(data_type.rules.first.config).to eq({ 'data_type_identifier' => { 'generic_key' => 'T' } }) end context 'with dependent data types' do From 9efe9d5468e23b016f7158370e5084fc2efc0511 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Wed, 26 Nov 2025 17:17:00 +0100 Subject: [PATCH 3/5] Fix grpc rule logic --- .../runtimes/data_types/update_service.rb | 22 +++++++++---------- .../runtimes/flow_types/update_service.rb | 2 ++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/services/runtimes/data_types/update_service.rb b/app/services/runtimes/data_types/update_service.rb index 8bb4058a..618b1e64 100644 --- a/app/services/runtimes/data_types/update_service.rb +++ b/app/services/runtimes/data_types/update_service.rb @@ -159,18 +159,16 @@ def update_rules(rules, data_type) db_rules = data_type.rules.first(rules.length) rules.each_with_index do |rule, index| config = rule.rule_config.to_h.transform_values do |value| - case value - when Tucana::Shared::DataTypeIdentifier - if value.data_type_identifier.present? - value.data_type_identifier - elsif value.generic_key.present? - { generic_key: value.generic_key } - else - { generic_type: value.generic_type } - end - else - value - end + next value unless value.is_a?(Hash) + + data_type_identifier = value[:data_type_identifier] + generic_key = value[:generic_key] + + next value if data_type_identifier.nil? || generic_key.nil? # return the old thing if neither is present + next data_type_identifier unless data_type_identifier.empty? # return data_type_identifier if it's present + next { generic_key: generic_key } if generic_key.present? # return generic_key if it's present + + next { generic_type: value[:generic_type] } end db_rules[index] ||= DataTypeRule.new diff --git a/app/services/runtimes/flow_types/update_service.rb b/app/services/runtimes/flow_types/update_service.rb index 13e2674f..5ec10bb1 100644 --- a/app/services/runtimes/flow_types/update_service.rb +++ b/app/services/runtimes/flow_types/update_service.rb @@ -36,6 +36,8 @@ def execute UpdateRuntimeCompatibilityJob.perform_later({ runtime_id: current_runtime.id }) + logger.info(message: 'Updated flow types for runtime', runtime_id: current_runtime.id) + ServiceResponse.success(message: 'Updated data types', payload: flow_types) end end From 05bce2b5edb9bd8511bc004d638d8135751b0131 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Wed, 26 Nov 2025 22:04:24 +0100 Subject: [PATCH 4/5] Revert some changes because it will be fixed via tucana changes --- .../runtimes/data_types/update_service.rb | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/app/services/runtimes/data_types/update_service.rb b/app/services/runtimes/data_types/update_service.rb index 618b1e64..ec836d8c 100644 --- a/app/services/runtimes/data_types/update_service.rb +++ b/app/services/runtimes/data_types/update_service.rb @@ -158,24 +158,8 @@ def find_data_type(identifier, t) def update_rules(rules, data_type) db_rules = data_type.rules.first(rules.length) rules.each_with_index do |rule, index| - config = rule.rule_config.to_h.transform_values do |value| - next value unless value.is_a?(Hash) - - data_type_identifier = value[:data_type_identifier] - generic_key = value[:generic_key] - - next value if data_type_identifier.nil? || generic_key.nil? # return the old thing if neither is present - next data_type_identifier unless data_type_identifier.empty? # return data_type_identifier if it's present - next { generic_key: generic_key } if generic_key.present? # return generic_key if it's present - - next { generic_type: value[:generic_type] } - end - db_rules[index] ||= DataTypeRule.new - db_rules[index].assign_attributes( - variant: rule.variant.to_s.downcase, - config: config - ) + db_rules[index].assign_attributes(variant: rule.variant.to_s.downcase, config: rule.rule_config.to_h) end db_rules From 6fe50bffbfaddaffc32b38acff581f5972a892f9 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Thu, 27 Nov 2025 15:34:28 +0100 Subject: [PATCH 5/5] Bump tucana version to 0.0.42 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index bbcc6093..ed041571 100644 --- a/Gemfile +++ b/Gemfile @@ -79,7 +79,7 @@ gem 'good_job', '~> 4.0' gem 'rotp' gem 'grpc', '~> 1.67' -gem 'tucana', '0.0.41' +gem 'tucana', '0.0.42' gem 'code0-identities', '~> 0.0.2' diff --git a/Gemfile.lock b/Gemfile.lock index e4d618f2..4a8c2a2c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -376,7 +376,7 @@ GEM thor (1.4.0) timeout (0.4.4) tsort (0.2.0) - tucana (0.0.41) + tucana (0.0.42) grpc (~> 1.64) tzinfo (2.0.6) concurrent-ruby (~> 1.0) @@ -430,7 +430,7 @@ DEPENDENCIES simplecov (~> 0.22.0) simplecov-cobertura (~> 3.0) test-prof (~> 1.0) - tucana (= 0.0.41) + tucana (= 0.0.42) tzinfo-data RUBY VERSION