How to connect to different collections in solr from one Rails application? - ruby-on-rails

I am trying to create a multi-tenant architecture and I am hoping to use separate solr collections for different tenants.
I am using sunspot-solr to interact with the Solr Server.
The sunspot.yml file looks as below :
production:
solr:
hostname: 127.0.0.1
port: 8983
log_level: WARNING
path: /solr/collection_1
read_timeout: 2
open_timeout: 0.5
development:
solr:
hostname: 127.0.0.1
port: 8983
log_level: INFO
path: /solr/collection
test:
solr:
hostname: localhost
port: 8983
log_level: WARNING
path: /solr/collection
My Model looks like this:
class ContentMaster < ActiveRecord::Base
self.table_name = "content_master"
searchable do
text :title, :stored => true
string :id, :multiple => true, :stored => true
integer :status, :multiple => true
string :image_url, :stored => true
end
end
And this is how I am fetching the content from Solr:
#search = ContentMaster.search do
fulltext search_word
with(:status,1)
end
Now, Everything is working fine for a single collection
Please guide me on the following :
How do I configure my sunspot.yml file to incorporate multiple collection(core) paths.
What changes do I need to make(if any) in my models to index data
for different tenants.
What changes do I need to make(if any) in my data extraction mechanism for different tenants.
Any help is appreciated. Thanks...!!!

Related

How can I start my Elasticsearch service correctly on ruby on rails (V7)

I am working on integrating elasticsearch to a ruby on rails apps (With elasticsearch-model gem). However, Whenever I send a request it returns the following error:
{"#timestamp":"2022-04-09T02:43:05.554Z", "log.level": "WARN", "message":"received plaintext http traffic on an https channel, closing connection Netty4HttpChannel{localAddress=/192.168.128.3:9200, remoteAddress=/192.168.128.6:38770}", "ecs.version": "1.2.0","service.name":"ES_ECS","event.dataset":"elasticsearch.server","process.thread.name":"elasticsearch[73415b48aadd][transport_worker][T#3]","log.logger":"org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4HttpServerTransport","elasticsearch.cluster.uuid":"5_0N8RB0Roq4iE_nqniR2Q","elasticsearch.node.id":"3E0mbrjiSQKCjaZ5PopG2A","elasticsearch.node.name":"73415b48aadd","elasticsearch.cluster.name":"docker-cluster"}
Completed 500 Internal Server Error in 154ms (ActiveRecord: 5.1ms | Allocations: 18974)
Faraday::ConnectionFailed (end of file reached):
app/controllers/api/v1/messages_controller.rb:33:in `puts'
app/controllers/api/v1/messages_controller.rb:33:in `puts'
app/controllers/api/v1/messages_controller.rb:33:in `show'
Piece of code that causes this issue :
def show
begin
#message = Message.search(1)
rescue ActiveRecord::RecordNotFound => e
render json: {message: "Message isn't found"} , status: 400
return
end
puts #message
render json: #message
end
messages model file :
class Message < ApplicationRecord
include Searchable
belongs_to :app , foreign_key: 'app_token', primary_key: 'app_token', optional: true
end
Searchable file:
module Searchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
mappings do
indexes :message_number ,type: 'integer'
indexes :body ,type: 'text'
indexes :app_token ,type: 'string'
indexes :chat_number ,type: 'integer'
end
def self.search(_query)
__elasticsearch__.search({
query: {
match:
{
body: "test"
}
}
}).records
end
end
end
Notice that I use a dummy query to test connectivity that's all
Docker-compose service for elasticsearch
elasticsearch:
image: elasticsearch:8.1.2
ports:
- "9300:9200"
app:
platform: linux/x86_64
restart: on-failure
build: .
command: bash -c "sh init.sh"
volumes:
- ".:/app"
ports:
- "3000:3000"
depends_on:
- elasticsearch
And finally elasticsearch initializer
Elasticsearch::Model.client = Elasticsearch::Client.new({host:'elasticsearch'})
I use an M1 machine and it caused lots of problems while working, so Idk if that's any relevant to that problem

Rails adding extra line in my redis cache

Im using redis-rails in my project to store a cache of users, and I don't know why a extra line is added at begining of cache.
This is my config:
config.cache_store = :redis_store, {
host: ENV['REDIS_SERVER'] || 'localhost',
port: 6379,
db: 0,
namespace: ENV['CUSTOMER']
}
This is my code:
namespace :update_employees_cache do
desc "Update employees cache"
task update: :environment do
employees = []
Employee.where(active: true).each do |item|
employees.push({ id: item.id, name: item.name })
end
Rails.cache.write "employees", employees.to_json
end
end
This is the result
At line 1, o: ActiveSupport::Cache::Entry:#valueI"�
What is this?
After open a issue in the project repo I discovered that is the default behavior of rails wrapping the cache with that data.
In my case I need to avoid it, then is needed set row as true in configs.
config.cache_store = :redis_store, {
host: ENV['REDIS_SERVER'] || 'localhost',
port: 6379,
db: 0,
namespace: ENV['CUSTOMER'],
raw: true
}

Grails returns server error after creating domain class

I am a newbie to Grails and I am stuck with the GORM part. I tried to follow tutorial on this site http://grails.asia/grails-tutorial-for-beginners-introduction-to-gorm about GORM and the first thing to do is create a domain class. However, after following the instructions there, I always received the error showed below.
My controller for inserting record
package nba
class PlayerController {
def index() {
//render "It's game time! NBA Game time"
Player p = new Player()
p.fname = "Lebron"
p.lname = "James"
p.position = "Small Forward"
p.age = 30
}
}
. What is the problem with this. What am I lacking? Please help.
---
grails:
profile: web
codegen:
defaultPackage: myapp
info:
app:
name: '#info.app.name#'
version: '#info.app.version#'
grailsVersion: '#info.app.grailsVersion#'
spring:
groovy:
template:
check-template-location: false
---
grails:
mime:
disable:
accept:
header:
userAgents:
- Gecko
- WebKit
- Presto
- Trident
types:
all: '*/*'
atom: application/atom+xml
css: text/css
csv: text/csv
form: application/x-www-form-urlencoded
html:
- text/html
- application/xhtml+xml
js: text/javascript
json:
- application/json
- text/json
multipartForm: multipart/form-data
pdf: application/pdf
rss: application/rss+xml
text: text/plain
hal:
- application/hal+json
- application/hal+xml
xml:
- text/xml
- application/xml
urlmapping:
cache:
maxsize: 1000
controllers:
defaultScope: singleton
converters:
encoding: UTF-8
views:
default:
codec: html
gsp:
encoding: UTF-8
htmlcodec: xml
codecs:
expression: html
scriptlets: html
taglib: none
staticparts: none
---
hibernate:
cache:
queries: false
use_second_level_cache: true
use_query_cache: false
region.factory_class: 'org.hibernate.cache.ehcache.EhCacheRegionFactory'
endpoints:
jmx:
unique-names: true
dataSource:
pooled: true
jmxExport: true
driverClassName: com.mysql.jdbc.Driver
environments:
development:
dataSource:
dbCreate: create-drop
url: jdbc:mysql://localhost/grails_db
username: root
password:
test:
dataSource:
dbCreate: update
url: jdbc:mysql://localhost/grails_db
production:
dataSource:
dbCreate: update
url: jdbc:mysql://localhost/grails_db
properties:
jmxEnabled: true
initialSize: 5
maxActive: 50
minIdle: 5
maxIdle: 25
maxWait: 10000
maxAge: 600000
timeBetweenEvictionRunsMillis: 5000
minEvictableIdleTimeMillis: 60000
validationQuery: SELECT 1
validationQueryTimeout: 3
validationInterval: 15000
testOnBorrow: true
testWhileIdle: true
testOnReturn: false
jdbcInterceptors: ConnectionState
defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED
Sorry I didn't see your comment:
Firstly to expand on my comment above and explain grails controller behaviour better. I will stick with render you have other choices.
When declaring an action in your controller:
so lets say we have
class TestController {
def hello() { }
}
You may or may not have a domainClass bound to this example TestController, if you did the domain class would be {package}/Test.groovy {matching the naming construct of controller}.
In this example we have no domain controller and above action will show something as long as you create a folder under views called
test/hello.gsp
So in that test folder you create hello.gsp and put in there some html..
If you didn't have
test/hello.gsp
Then in your controller you would have to define what to render.
class TestController {
def hello() {
// render 'some text'
//render template: '/path/to/template', model: [params:params]
render view: '/path/to/gsp', model: [params:params]
}
}
You then state:
This is how I got the error, when I created a domain class player and
then put the field names (fname, lname, position, age), it was
successful, the table player is created in the database together with
field names but when I restarted running the server, the table was
deleted automatically and the running back the server returns error.
What is the problem with that?
Firstly you need to then ask yourself, did you configure/install some DB in order to see it working initially?
Grails provides you with an inbuilt DB that resides in your memory as part of its default app creation.In short a fresh DB is triggered on each run app.
E2A
Pay attention to dbCreate line:
create-drop : Creates tables on application startup and drops then when shutdown
create : Creates all tables at app start up
update : Updates existing tables (will not attempt to create any. that's down to you)
http://grails.github.io/grails-doc/3.0.x/guide/conf.html
In development mode dbCreate is by default set to "create-drop", but
at some point in development (and certainly once you go to production)
you'll need to stop dropping and re-creating the database every time
you start up your server.

Rails4 charset issue when connect to remote MySQL DB

I use next settings to connect to remote DB:
class MyModel < ActiveRecord::Base
self.table_name = 'users'
establish_connection(
adapter: "mysql2",
host: "host_ip",
encoding: "koi8u",
username: "custom_name",
password: "password",
database: "db_name")
end
It connects well but when I make a query, I receive something like Address: "п⌠п╟п╪п╟п?п╦п? п░п╩я▄я├п╣я│я┌"
I also try another variant of connection like:
connection = Mysql2::Client.new( host: 'host_name',
username: 'user',
password: 'password',
port: 3306,
database: 'db_name',
encoding: 'koi8u',
reconnect: true
)
In this case I receive connection object, but can't make a query... When I use
connection.query("SELECT * FROM users") it returns me the connection object...
Also when I check encoding it returns:
MyModel.first.Address.encoding.name
MyModel Load (6.8ms) SELECT `users`.* FROM `users` ORDER BY `users`.`login` ASC LIMIT
1
=> "UTF-8"
When in settings I use koi8u !
I was checking charset on MySQL server in this DB - it is set to koi8u !
Any ideas? I need to connect to this DB with normal charset
It seems to me that your database locale is different then you expect it to be
Did you changed it or set it in any stage?
It is not enough to declare about it in the connection string
You can find up here how to check what is your database character set
How do I see what character set a MySQL database / table / column is?

Multiple databases support in Symfony

I am using Propel as my DAL for my Symfony project. I can't seem to get my application to work across two or more databases.
Here's my schema.yml:
db1:
lkp_User:
pk_User: { type: integer, required: true, primaryKey: true, autoIncrement: true }
UserName: { type: varchar(45), required: true }
Password: longvarchar
_uniques:
Unique: [ UserName ]
db2:
tesco:
Id: { type: integer, required: true, primaryKey: true, autoIncrement: true }
Name: { type: varchar(45), required: true }
Description: longvarchar
And here's the databases.yml:
dev:
db1:
param:
classname: DebugPDO
test:
db1:
param:
classname: DebugPDO
all:
db1:
class: sfPropelDatabase
param:
classname: PropelPDO
dsn: 'mysql:dbname=bpodb;host=localhost' #where the db is located
username: root
password: #pass
encoding: utf8
persistent: true
pooling: true
db2:
class: sfPropelDatabase
param:
classname: PropelPDO
dsn: 'mysql:dbname=mystore2;host=localhost' #where the db is located
username: root
password: #pass
encoding: utf8
persistent: true
pooling: true
When I call php symfony propel-build-model, only db1 is generated, db2 is not.
Any idea how to fix this problem?
I got this issue working! The most important thing is you must name your schema according to %dbname%.schema.yml. In this way Symfony will be able to assign the ymls to the correct database.
Also when running the task you should specify the connection for example:
symfony propel:build-all-load --connection=my_connection
This worked for me, hope it helps.
You can also use Propel::getConnection('db2') to manually retrieve a connection.
Just have in mind that what you call "db1", "db2" are the connection names. You can have several connections to a same database with various login/permissions (like read only etc.).
It's very good for testing purpose: you can do it with the same connection name with a different database. No way to crash your production database with that :)

Resources