s3arch 0.0.4 → 0.0.6.alpha

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.

Potentially problematic release.


This version of s3arch might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b5d2b31636cdd8dd3d02bfd8140a82263f462207bf80525ef55167e1267a057
4
- data.tar.gz: 8cfa541ae296debeb4ca01737673733805b81268a415280241a57eaba1f22821
3
+ metadata.gz: 76cbfbd7db2c11d924729920685cfbd50525fa31e24dda087ab8a2ce4e9c03a4
4
+ data.tar.gz: 6256c7ff9391e7b57d40a9ce7f9751a1960142229480fddcf75fd9bd067bd352
5
5
  SHA512:
6
- metadata.gz: fd0c3fabee28274d50d46951fde563bc9196263d59174ee87047bdb8a06d7ae1ee7964ae82d431c6c22ee875e40512918a01c6110292d0a0d06c89e54201e25e
7
- data.tar.gz: '008755884d519604931a7ccfebff4492c0308900230d5e9cd535aa452afb9e7a48d9274c04b15867b2bfd3bbe031aeb2ae08d1c2b6ffdf8759a7a90518ce7b60'
6
+ metadata.gz: 8cc3ec77fbc57dba507db244b0b67d9810506ae113667ded39e588f8b713440f2ec1e20616592901698bec3d774f38d08a47720d8b1af6b30e6439578dcf17cf
7
+ data.tar.gz: b3f46f36ab31bc07cca101bad5ee10e1d978b4d090ea6911375dfdc9e3a66b2c3984d180133bffd203f2ac2f571b81bd051da056d287d844efdb769fe46492d0
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ TerraDispatch.routes.draw do
4
+ namespace :s3arch, auth: :cognito, tables: [:search_indexes] do
5
+ get '/', action: 'index'
6
+ post '/rebuild', action: 'rebuild'
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ TerraDispatch.schema.define do
4
+ # S3arch does not define request/response models yet.
5
+ # The search_indexes table is provisioned by s3arch's own Terraform module.
6
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sdk-dynamodb'
4
+
5
+ class S3archController < BeltController::Base
6
+ def index
7
+ owners = fetch_owners
8
+ success_response(owners: owners)
9
+ rescue StandardError => e
10
+ error_response("Failed to load s3arch dashboard: #{e.message}", 500)
11
+ end
12
+
13
+ def rebuild
14
+ owner_id = params['owner_id']&.strip
15
+ return error_response('owner_id is required', 400) if owner_id.nil? || owner_id.empty?
16
+
17
+ handler = S3arch.configuration.rebuild_handler
18
+ if handler
19
+ handler.call(owner_id)
20
+ else
21
+ S3arch::Indexer.new.rebuild(owner_id)
22
+ end
23
+ success_response(status: 'ok', owner_id: owner_id)
24
+ rescue StandardError => e
25
+ error_response("Failed to rebuild index: #{e.message}", 500)
26
+ end
27
+
28
+ private
29
+
30
+ def fetch_owners
31
+ dynamodb = Aws::DynamoDB::Client.new
32
+ config = S3arch.configuration
33
+ items = []
34
+ scan_params = { table_name: config.version_table }
35
+
36
+ loop do
37
+ result = dynamodb.scan(scan_params)
38
+ items.concat(result.items)
39
+ break unless result.last_evaluated_key
40
+
41
+ scan_params[:exclusive_start_key] = result.last_evaluated_key
42
+ end
43
+
44
+ owners = items.map do |item|
45
+ {
46
+ owner_id: item[config.owner_key] || item.values.first,
47
+ version: item['version'],
48
+ record_count: item['record_count'],
49
+ updated_at: item['updated_at']
50
+ }
51
+ end
52
+ owners.sort_by { |o| o[:updated_at].to_s }.reverse
53
+ end
54
+ end
@@ -42,6 +42,11 @@ module S3arch
42
42
  # Searcher settings
43
43
  attr_accessor :version_ttl, :max_results, :max_cached_dbs, :ephemeral_storage_mb
44
44
 
45
+ # Custom rebuild handler — proc/lambda that receives owner_id.
46
+ # When set, the controller uses this instead of calling Indexer.new.rebuild directly.
47
+ # Useful for triggering rebuilds via Lambda invocation instead of in-process.
48
+ attr_accessor :rebuild_handler
49
+
45
50
  def initialize
46
51
  @owner_key = 'user_id'
47
52
  @searchable_fields = %w[name description]
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+ require 'json'
5
+ require 'aws-sdk-dynamodb'
6
+
7
+ module S3arch
8
+ module Dashboard
9
+ class Application
10
+ VIEWS_PATH = File.expand_path('views', __dir__)
11
+
12
+ # Dispatcher mount DSL contract — keep in sync with #call dispatch below.
13
+ def routes
14
+ [
15
+ { method: :get, path: '/' },
16
+ { method: :post, path: '/rebuild' }
17
+ ]
18
+ end
19
+
20
+ def call(env)
21
+ req = Rack::Request.new(env)
22
+ path = req.path_info.sub(%r{^/}, '')
23
+
24
+ case [req.request_method, path]
25
+ when ['GET', ''], %w[GET index]
26
+ index(req)
27
+ when %w[POST rebuild]
28
+ rebuild(req)
29
+ else
30
+ [404, { 'content-type' => 'text/plain' }, ['Not Found']]
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def index(req)
37
+ @env = req.env
38
+ @owners = fetch_owners
39
+ html = render('index')
40
+ [200, { 'content-type' => 'text/html' }, [html]]
41
+ end
42
+
43
+ def rebuild(req)
44
+ owner_id = req.params['owner_id']&.strip
45
+ if owner_id && !owner_id.empty?
46
+ indexer = S3arch::Indexer.new
47
+ indexer.rebuild(owner_id)
48
+ end
49
+ [303, { 'location' => "#{req.script_name}/" }, []]
50
+ end
51
+
52
+ def fetch_owners
53
+ config = S3arch.configuration
54
+ dynamodb = Aws::DynamoDB::Client.new
55
+ items = []
56
+ params = { table_name: config.version_table }
57
+
58
+ loop do
59
+ result = dynamodb.scan(params)
60
+ items.concat(result.items)
61
+ break unless result.last_evaluated_key
62
+
63
+ params[:exclusive_start_key] = result.last_evaluated_key
64
+ end
65
+
66
+ owners = items.map do |item|
67
+ {
68
+ owner_id: item[config.owner_key] || item.values.first,
69
+ version: item['version'],
70
+ record_count: item['record_count'],
71
+ updated_at: item['updated_at']
72
+ }
73
+ end
74
+ owners.sort_by { |o| o[:updated_at].to_s }.reverse
75
+ rescue StandardError => e
76
+ @error = e.message
77
+ []
78
+ end
79
+
80
+ def render(template)
81
+ path = File.join(VIEWS_PATH, "#{template}.html.erb")
82
+ ERB.new(File.read(path), trim_mode: '-').result(binding)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,61 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>S3arch Dashboard</title>
5
+ <style>
6
+ * { box-sizing: border-box; margin: 0; padding: 0; }
7
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 2rem; }
8
+ h1 { margin-bottom: 1.5rem; }
9
+ .error { background: #fee; border: 1px solid #fcc; padding: 0.75rem; border-radius: 4px; margin-bottom: 1rem; color: #c00; }
10
+ table { width: 100%; border-collapse: collapse; background: #fff; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
11
+ th, td { padding: 0.75rem 1rem; text-align: left; border-bottom: 1px solid #eee; }
12
+ th { background: #fafafa; font-weight: 600; }
13
+ form.inline { display: inline; }
14
+ button { background: #2563eb; color: #fff; border: none; padding: 0.4rem 0.8rem; border-radius: 4px; cursor: pointer; font-size: 0.85rem; }
15
+ button:hover { background: #1d4ed8; }
16
+ .rebuild-all { margin-bottom: 1rem; }
17
+ .rebuild-all button { background: #dc2626; }
18
+ .rebuild-all button:hover { background: #b91c1c; }
19
+ .empty { padding: 2rem; text-align: center; color: #666; }
20
+ </style>
21
+ </head>
22
+ <body>
23
+ <h1>S3arch Dashboard</h1>
24
+
25
+ <%- if @error -%>
26
+ <div class="error"><strong>Error:</strong> <%= @error %></div>
27
+ <%- end -%>
28
+
29
+ <%- if @owners.any? -%>
30
+ <table>
31
+ <thead>
32
+ <tr>
33
+ <th>Owner</th>
34
+ <th>Version</th>
35
+ <th>Records</th>
36
+ <th>Last Updated</th>
37
+ <th>Actions</th>
38
+ </tr>
39
+ </thead>
40
+ <tbody>
41
+ <%- @owners.each do |owner| -%>
42
+ <tr>
43
+ <td><%= owner[:owner_id] %></td>
44
+ <td><%= owner[:version] %></td>
45
+ <td><%= owner[:record_count] || '—' %></td>
46
+ <td><%= owner[:updated_at] || '—' %></td>
47
+ <td>
48
+ <form class="inline" method="post" action="<%= @env['SCRIPT_NAME'] %>/rebuild">
49
+ <input type="hidden" name="owner_id" value="<%= owner[:owner_id] %>">
50
+ <button type="submit">Rebuild</button>
51
+ </form>
52
+ </td>
53
+ </tr>
54
+ <%- end -%>
55
+ </tbody>
56
+ </table>
57
+ <%- else -%>
58
+ <div class="empty">No indexed owners found.</div>
59
+ <%- end -%>
60
+ </body>
61
+ </html>
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'erb'
5
+ require_relative 'dashboard/application'
6
+
7
+ module S3arch
8
+ module Dashboard
9
+ def self.app
10
+ Application.new
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module S3arch
4
+ class Holster < Belt::Holster
5
+ self.gem_root = File.expand_path('../..', __dir__)
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module S3arch
4
+ # Lightweight route manifest for Dispatcher mount DSL.
5
+ # No heavy dependencies — safe to load in parse-only contexts.
6
+ module Routes
7
+ def self.routes
8
+ [
9
+ { method: :get, path: '/' },
10
+ { method: :post, path: '/rebuild' }
11
+ ]
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module S3arch
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.6.alpha'
5
5
  end
data/lib/s3arch/web.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Lightweight S3arch load for web/API contexts (no SQLite dependency).
4
+ # Provides configuration, holster registration, and routes only.
5
+ require_relative 'version'
6
+ require_relative 'configuration'
7
+ require_relative 'routes'
8
+ require_relative 'holster'
9
+
10
+ module S3arch
11
+ class Error < StandardError; end
12
+
13
+ class << self
14
+ def configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def configure
19
+ yield(configuration)
20
+ end
21
+
22
+ def reset_configuration!
23
+ @configuration = Configuration.new
24
+ end
25
+ end
26
+ end
data/lib/s3arch.rb CHANGED
@@ -6,6 +6,11 @@ require_relative 's3arch/tokenizer'
6
6
  require_relative 's3arch/indexer'
7
7
  require_relative 's3arch/searcher'
8
8
  require_relative 's3arch/handler'
9
+ require_relative 's3arch/routes'
10
+ require_relative 's3arch/dashboard'
11
+
12
+ # Register as a Belt holster when Belt is loaded
13
+ require_relative 's3arch/holster' if defined?(Belt::Holster)
9
14
 
10
15
  module S3arch
11
16
  class Error < StandardError; end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3arch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Dalton
@@ -64,6 +64,20 @@ dependencies:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '1.0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rack
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '2.0'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '2.0'
67
81
  - !ruby/object:Gem::Dependency
68
82
  name: sqlite3
69
83
  requirement: !ruby/object:Gem::Requirement
@@ -78,8 +92,8 @@ dependencies:
78
92
  - - "~>"
79
93
  - !ruby/object:Gem::Version
80
94
  version: '2.0'
81
- description: Per-owner SQLite FTS5 indexes stored on S3, queried from Lambda /tmp.
82
- DynamoDB source records are indexed via streams, with version tracking and LRU caching.
95
+ description: Per-owner SQLite FTS5 indexes stored on S3, queried from Lambda /tmp
96
+ with version tracking.
83
97
  email:
84
98
  - adam@stowzilla.com
85
99
  executables: []
@@ -90,13 +104,22 @@ files:
90
104
  - LICENSE.txt
91
105
  - README.md
92
106
  - certs/stowzilla.pem
107
+ - infrastructure/routes.tf.rb
108
+ - infrastructure/schema.tf.rb
109
+ - lambda/controllers/s3arch_controller.rb
93
110
  - lib/s3arch.rb
94
111
  - lib/s3arch/configuration.rb
112
+ - lib/s3arch/dashboard.rb
113
+ - lib/s3arch/dashboard/application.rb
114
+ - lib/s3arch/dashboard/views/index.html.erb
95
115
  - lib/s3arch/handler.rb
116
+ - lib/s3arch/holster.rb
96
117
  - lib/s3arch/indexer.rb
118
+ - lib/s3arch/routes.rb
97
119
  - lib/s3arch/searcher.rb
98
120
  - lib/s3arch/tokenizer.rb
99
121
  - lib/s3arch/version.rb
122
+ - lib/s3arch/web.rb
100
123
  homepage: https://github.com/stowzilla/s3arch
101
124
  licenses:
102
125
  - MIT
metadata.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- �٣��b���A��t��1<ۈճ;w�@��^�����(,Z��\�r����XZƠ��B���:DewV�ԭ�h���x�KNI��%,`�Tf��8C��@��r;f��l}�7F�==T�V��b/!MP��ι[̦ @�ȁ��<�t�R���ȜX�uu�d�H��k�T��!��A�N~�_���^atOZ�p%h�{�n� ��fMT�Y_�'g��=�#���/���6!��TS(�|�l����7ݸ���{��
2
- ��e~ʞ���uE���BG�S�7����ݼ�����*�q=�6r_r��Q�P�|g�]�V]j��+ˍ���Qú�.B�������r
1
+ ���ˁ�y����.�T���C�˧������!�(��Dz9alafg�c����
2
+ ��8s(�.���0��Sq�EV2/)�! 9�힛�e��v��@��8���.���������]x"��w��F�����]%B����Ơ(\�FIa<����|��N'��ܯ��*V