harmonia 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b3d138727a59279aa27d27f45c4f829b6fb579aaff1fcb1f96f8c9af4de7a2c
|
|
4
|
+
data.tar.gz: 11efb0c921eaa4d3781b475e386cd617f3bc029bc463e67f1c7be544caf4cdbe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85bc5b955d18ffdc0e86b276d43de07589909517cb28dd1bdaeddb6039380d4987c2f8db02d6a429cb9ad5b75221ca5b23eb0e7f9f2c674482ab6c7b4ff428cb
|
|
7
|
+
data.tar.gz: 0727cc7e6b2c6e8dcb2ebaf2a2934aa2e5cad18c3f6cfd8b4438dbc0ac6ccf5caf3b4774c6e482a51f75732c0b96e864f75ab19ee1c95fb43103bd980f09968a
|
|
@@ -10,6 +10,8 @@ class CreateHarmoniaSyncs < ActiveRecord::Migration[<%= Rails::VERSION::MAJOR %>
|
|
|
10
10
|
t.string :status, default: 'pending'
|
|
11
11
|
t.string :direction
|
|
12
12
|
t.text :error_message
|
|
13
|
+
t.string :failed_fm_ids, array: true
|
|
14
|
+
t.integer :failed_pg_ids, array: true
|
|
13
15
|
|
|
14
16
|
t.timestamps
|
|
15
17
|
end
|
|
@@ -6,6 +6,8 @@ class <%= class_name %>Syncer
|
|
|
6
6
|
def initialize(database_connector)
|
|
7
7
|
@database_connector = database_connector
|
|
8
8
|
@last_synced_on = Harmonia::Sync.last_sync_for('<%= table_name %>', 'FileMaker to ActiveRecord')&.ran_on || (Time.now - 15.year)
|
|
9
|
+
@failed_fm_ids = []
|
|
10
|
+
@failed_pg_ids = []
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
# Main sync method
|
|
@@ -20,7 +22,7 @@ class <%= class_name %>Syncer
|
|
|
20
22
|
sync_records(sync_record)
|
|
21
23
|
end
|
|
22
24
|
rescue StandardError => e
|
|
23
|
-
sync_record&.fail!(e.message)
|
|
25
|
+
sync_record&.fail!(e.message, failed_fm_ids: @failed_fm_ids, failed_pg_ids: @failed_pg_ids)
|
|
24
26
|
raise
|
|
25
27
|
end
|
|
26
28
|
|
|
@@ -36,55 +38,68 @@ class <%= class_name %>Syncer
|
|
|
36
38
|
|
|
37
39
|
sync_record.finish!(
|
|
38
40
|
records_synced: total_synced,
|
|
39
|
-
records_required: total_required
|
|
41
|
+
records_required: total_required,
|
|
42
|
+
failed_fm_ids: @failed_fm_ids,
|
|
43
|
+
failed_pg_ids: @failed_pg_ids
|
|
40
44
|
)
|
|
41
45
|
end
|
|
42
46
|
|
|
43
47
|
# Returns an array of Trophonius records that need to be created
|
|
44
|
-
# Use
|
|
48
|
+
# Use FileMaker::<%= class_name %>.to_pg(record) to convert to PostgreSQL attributes
|
|
45
49
|
# Set @total_create_required to the total number of records that should exist after creation
|
|
46
50
|
# @return [Array<Trophonius::Record>] Array of Trophonius records
|
|
47
51
|
def records_to_create
|
|
48
52
|
# TODO: Implement logic to fetch records from FileMaker that need to be created in PostgreSQL
|
|
49
53
|
# Example:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@total_create_required = 0
|
|
55
|
-
[]
|
|
54
|
+
filemaker_records = FileMaker::<%= class_name %>.where(creation_timestamp: ">= #{@last_synced_on.to_fm}").not
|
|
55
|
+
@total_create_required = filemaker_records.length
|
|
56
|
+
existing_ids = <%= class_name %>.pluck(:filemaker_id)
|
|
57
|
+
filemaker_records.reject { |record| existing_ids.include?(record.id) }
|
|
56
58
|
end
|
|
57
59
|
|
|
58
60
|
# Returns an array of Trophonius records that need to be updated
|
|
59
|
-
# Use
|
|
61
|
+
# Use FileMaker::<%= class_name %>.to_pg(record) to convert to PostgreSQL attributes
|
|
60
62
|
# Set @total_update_required to the total number of records that should be updated
|
|
61
63
|
# @return [Array<Trophonius::Record>] Array of Trophonius records
|
|
62
64
|
def records_to_update
|
|
63
65
|
# TODO: Implement logic to fetch records from FileMaker that need to be updated in PostgreSQL
|
|
64
66
|
# Example:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
@total_update_required = 0
|
|
73
|
-
[]
|
|
67
|
+
filemaker_records = FileMaker::<%= class_name %>.where(modification_timestamp: ">= #{@last_synced_on.to_fm}")
|
|
68
|
+
records_needing_update = filemaker_records.select { |fm_record|
|
|
69
|
+
pg_record = <%= class_name %>.find_by(filemaker_id: fm_record.record_id)
|
|
70
|
+
pg_record && needs_update?(fm_record, pg_record)
|
|
71
|
+
}
|
|
72
|
+
@total_update_required = records_needing_update.length
|
|
73
|
+
records_needing_update
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# Returns an array of record identifiers that need to be deleted
|
|
77
77
|
# @return [Array] Array of record identifiers
|
|
78
78
|
def records_to_delete
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
# Get all modified FileMaker record IDs
|
|
80
|
+
filemaker_records = FileMaker::<%= class_name %>.where(modification_timestamp: ">= #{@last_synced_on.to_fm}")
|
|
81
|
+
fm_ids = filemaker_records.map(&:record_id)
|
|
82
|
+
|
|
83
|
+
# Find PostgreSQL records whose FileMaker IDs aren't in the modified set
|
|
84
|
+
# These might have been deleted in FileMaker
|
|
85
|
+
fm_ids_no_update_needed = <%= class_name %>.where.not(filemaker_id: fm_ids).pluck(:filemaker_id)
|
|
86
|
+
return [] if fm_ids_no_update_needed.empty?
|
|
87
|
+
|
|
88
|
+
# Query FileMaker to check if these records still exist
|
|
89
|
+
possibly_deleted_query = FileMaker::<%= class_name %>.where(record_id: fm_ids_no_update_needed.first)
|
|
90
|
+
fm_ids_no_update_needed.count > 1 && fm_ids_no_update_needed[1..].each do |fm_id|
|
|
91
|
+
possibly_deleted_query.or(record_id: fm_id)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Find IDs that exist in PostgreSQL but not in FileMaker (truly deleted)
|
|
95
|
+
deleted_fm_ids = fm_ids_no_update_needed - possibly_deleted_query.map(&:record_id)
|
|
96
|
+
|
|
97
|
+
# Return PostgreSQL IDs for records with these FileMaker IDs
|
|
98
|
+
<%= class_name %>.where(filemaker_id: deleted_fm_ids).pluck(:id)
|
|
84
99
|
end
|
|
85
100
|
|
|
86
101
|
def needs_update?(fm_record, pg_record)
|
|
87
|
-
pg_attributes =
|
|
102
|
+
pg_attributes = FileMaker::<%= class_name %>.to_pg(fm_record)
|
|
88
103
|
|
|
89
104
|
pg_attributes.any? { |key, value| pg_record.send(key) != value }
|
|
90
105
|
end
|
|
@@ -93,37 +108,60 @@ class <%= class_name %>Syncer
|
|
|
93
108
|
records = records_to_create
|
|
94
109
|
return 0 if records.empty?
|
|
95
110
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
success_count = 0
|
|
112
|
+
|
|
113
|
+
records.each do |trophonius_record|
|
|
114
|
+
begin
|
|
115
|
+
attributes = FileMaker::<%= class_name %>.to_pg(trophonius_record).merge(
|
|
116
|
+
created_at: Time.current,
|
|
117
|
+
updated_at: Time.current
|
|
118
|
+
)
|
|
119
|
+
<%= class_name %>.create!(attributes)
|
|
120
|
+
success_count += 1
|
|
121
|
+
rescue StandardError => e
|
|
122
|
+
@failed_fm_ids << trophonius_record.record_id
|
|
123
|
+
Rails.logger.error("Failed to create record from FileMaker ID #{trophonius_record.record_id}: #{e.message}")
|
|
124
|
+
end
|
|
101
125
|
end
|
|
102
126
|
|
|
103
|
-
|
|
104
|
-
records.size
|
|
127
|
+
success_count
|
|
105
128
|
end
|
|
106
129
|
|
|
107
130
|
def update_records
|
|
108
131
|
records = records_to_update
|
|
109
132
|
return 0 if records.empty?
|
|
110
133
|
|
|
111
|
-
|
|
112
|
-
pg_attributes = YourTrophoniusModel.to_pg(trophonius_record)
|
|
134
|
+
success_count = 0
|
|
113
135
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
records.each do |trophonius_record|
|
|
137
|
+
begin
|
|
138
|
+
pg_attributes = FileMaker::<%= class_name %>.to_pg(trophonius_record)
|
|
139
|
+
|
|
140
|
+
<%= class_name %>.where(filemaker_id: trophonius_record.record_id).update_all(
|
|
141
|
+
pg_attributes.merge(updated_at: Time.current)
|
|
142
|
+
)
|
|
143
|
+
success_count += 1
|
|
144
|
+
rescue StandardError => e
|
|
145
|
+
@failed_fm_ids << trophonius_record.record_id
|
|
146
|
+
Rails.logger.error("Failed to update record from FileMaker ID #{trophonius_record.record_id}: #{e.message}")
|
|
147
|
+
end
|
|
117
148
|
end
|
|
118
149
|
|
|
119
|
-
|
|
150
|
+
success_count
|
|
120
151
|
end
|
|
121
152
|
|
|
122
153
|
def delete_records
|
|
123
154
|
ids = records_to_delete
|
|
124
155
|
return if ids.empty?
|
|
125
156
|
|
|
126
|
-
|
|
157
|
+
ids.each do |pg_id|
|
|
158
|
+
begin
|
|
159
|
+
<%= class_name %>.where(id: pg_id).destroy_all
|
|
160
|
+
rescue StandardError => e
|
|
161
|
+
@failed_pg_ids << pg_id
|
|
162
|
+
Rails.logger.error("Failed to delete record with PostgreSQL ID #{pg_id}: #{e.message}")
|
|
163
|
+
end
|
|
164
|
+
end
|
|
127
165
|
end
|
|
128
166
|
|
|
129
167
|
def create_sync_record
|
|
@@ -24,9 +24,9 @@ module Harmonia
|
|
|
24
24
|
scope :completed, -> { where(status: 'completed') }
|
|
25
25
|
scope :failed, -> { where(status: 'failed') }
|
|
26
26
|
|
|
27
|
-
# Get the most recent sync for a table in a given direction
|
|
27
|
+
# Get the most recent successful sync for a table in a given direction
|
|
28
28
|
def self.last_sync_for(table_name, direction)
|
|
29
|
-
for_direction(direction).for_table(table_name).recent.first
|
|
29
|
+
completed.for_direction(direction).for_table(table_name).recent.first
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# Calculate sync completion percentage
|
|
@@ -46,19 +46,23 @@ module Harmonia
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# Mark sync as completed
|
|
49
|
-
def finish!(records_synced:, records_required:)
|
|
49
|
+
def finish!(records_synced:, records_required:, failed_fm_ids: [], failed_pg_ids: [])
|
|
50
50
|
update!(
|
|
51
51
|
status: 'completed',
|
|
52
52
|
records_synced: records_synced,
|
|
53
|
-
records_required: records_required
|
|
53
|
+
records_required: records_required,
|
|
54
|
+
failed_fm_ids: failed_fm_ids,
|
|
55
|
+
failed_pg_ids: failed_pg_ids
|
|
54
56
|
)
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
# Mark sync as failed
|
|
58
|
-
def fail!(error_message)
|
|
60
|
+
def fail!(error_message, failed_fm_ids: [], failed_pg_ids: [])
|
|
59
61
|
update!(
|
|
60
62
|
status: 'failed',
|
|
61
|
-
error_message: error_message
|
|
63
|
+
error_message: error_message,
|
|
64
|
+
failed_fm_ids: failed_fm_ids,
|
|
65
|
+
failed_pg_ids: failed_pg_ids
|
|
62
66
|
)
|
|
63
67
|
end
|
|
64
68
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: harmonia
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kempen Automatisering
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-11-
|
|
11
|
+
date: 2025-11-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: trophonius
|