Rabbitmq передает сообщения. И сообщения частенько очень важные.
Что б не терять их, при отказе железки, можно использовать rabbitmq cluster.
Но есть один ньюанс - в кластере, по умолчанию, очередь хранится на одной ноде.
Добавляем в опции очереди x-ha-policy => all и теперь копии очереди есть на всех нодах и если одна упадет , сообщения не потеряются.
Клиентская программа должна знать куда переподключаться в случае падения и использовать подтверждение о получении сообщения.
среда, 1 февраля 2012 г.
суббота, 28 января 2012 г.
deploy spree to openshift
Instruction how to deploy spreecommerce to openshift
work with ruby 1.8.7 because openshift work with this version.
ruby 1.9. hash syntax will create problem in openshift cloud
1. create application on openshift
Создалось приложение в облаке редхата и папочка spree с простым rack приложением.
А нам надо создать rails приложение с гемами spree.
Обратите внимание - используем постгрес(дело вкуса конечно,но все ж знают, что постгрес вкуснее)
2. add database(postgresql)
Если понадобится удалить подключенную базу
По завершению мы получим данные для подключения к базе.
Их стоит записать в spree/config/database.yml
и не забудьте добавить поле host и вписать ip из подобной строки Connection URL: postgresql://127.1.13.1:5432
И настроить базу для development режима
И в Gemfile добавляем гем sqlite3 для группы development
теперь перемещаемся в папку spree
добавляем сприи в Gemfile
Gemfile.lock должен быть актуальным
добавить код в .openshift/action_hooks/deploy
и теперь пушим git push
после удачного деплоя очищаем .openshift/action_hooks/deploy
first request will broken - it is problem on timeout parameter in proxy server.
but exist problem with timeout
P.S.
after few updates require use this database.yml
work with ruby 1.8.7 because openshift work with this version.
ruby 1.9. hash syntax will create problem in openshift cloud
1. create application on openshift
rhc-create-app -a spree -t rack-1.1Создалось приложение в облаке редхата и папочка spree с простым rack приложением.
А нам надо создать rails приложение с гемами spree.
rm -f ./spree/README rails new ./spree -d postgresql -f Обратите внимание - используем постгрес(дело вкуса конечно,но все ж знают, что постгрес вкуснее)
2. add database(postgresql)
rhc-ctl-app -a spree -e add-postgresql-8.4Если понадобится удалить подключенную базу
rhc-ctl-app -a spree -e remove-postgresql-8.4По завершению мы получим данные для подключения к базе.
Их стоит записать в spree/config/database.yml
и не забудьте добавить поле host и вписать ip из подобной строки Connection URL: postgresql://127.1.13.1:5432
И настроить базу для development режима
development:
adapter: sqlite3
database: db/dev.sqlite3
И в Gemfile добавляем гем sqlite3 для группы development
теперь перемещаемся в папку spree
bundle install && bundle exec rails g spree:installдобавляем сприи в Gemfile
echo "gem 'spree', :git => 'git://github.com/spree/spree.git'" >> ./GemfileGemfile.lock должен быть актуальным
bundle installmkdir public/images && cp public/favicon.ico public/images/favicon.icoRAILS_ENV=development bundle exec rake assets:precompileдобавить код в .openshift/action_hooks/deploy
pushd ${OPENSHIFT_REPO_DIR} > /dev/null
RAILS_ENV=production bundle exec rake db:migrate -y
RAILS_ENV=production bundle exec rake db:seed -y
popd > /dev/null
и теперь пушим git push
после удачного деплоя очищаем .openshift/action_hooks/deploy
first request will broken - it is problem on timeout parameter in proxy server.
but exist problem with timeout
P.S.
after few updates require use this database.yml
adapter: <%=ENV['OPENSHIFT_DB_TYPE']%>
encoding: utf8
host: <%=ENV['OPENSHIFT_DB_HOST']%>
port: <%=ENV['OPENSHIFT_DB_PORT']%>
socket: <%=ENV['OPENSHIFT_DB_SOCKET']%>
database: <%=ENV['OPENSHIFT_APP_NAME']%>
username: <%=ENV['OPENSHIFT_DB_USERNAME']%>
password: <%=ENV['OPENSHIFT_DB_PASSWORD']%>
воскресенье, 14 августа 2011 г.
Кеширование в мультидоменном веб приложении
добавляем в контроллер
в логах сразу видим как пишется
и при повторном запросе
Итого: с 300мс до 10 мс рендеринг страницы.
before_filter { |c|
   c.class.page_cache_directory = "#{RAILS_ROOT}/public/#{c.request.host}"
}
в логах сразу видим как пишется
Write fragment views/sub.domain.com/s/test (2.6ms)
и при повторном запросе
Read fragment views/sub.domain.com/s/test (0.9ms)
Итого: с 300мс до 10 мс рендеринг страницы.
среда, 3 августа 2011 г.
Получение в SproutCore нескольких массивов данных одним запросом к бакэнду.
Получение нескольких массивов данных одним запросом к бакэнду.
Допустим, у нас есть приложение Blog, в котором есть модели Blog.Post и Blog.Quote. Пусть они выводятся сервером по адресу '/records.json' и в json выглядят вот так:
Что бы уменьшить количество запросов к серверу и тем самым увеличить скорость получения данных, нам нужно немного изменить datasource приложения.
Шаг 1. Создать запрос:
В SC.Query.local можно передавать не только один тип записи, но и массив типов.
Шаг 2. Создать хэш-таблицу с ссылками на данные и типами записей:
Это шаг нужен что бы избежать огромного количества if в функции fetch()
Так же нам нужно поправить шан запрос, установив ему атрибум id, соответствующий имени одного из элементов urls, в данном случае posts_and_quotes:
Шаг 3. Пишем fetch():
Шаг 4. Обрабатываем полученные данные:
Шаг 5. Используем новый запрос в приложении:
Теперь, что бы получить отдельно posts, а отдельно quotes используем scoped queries:
Ну и теперь можно заполнить ArrayController'ы приложения полученными данными:
Полностью datasource будет выглядеть так:
Допустим, у нас есть приложение Blog, в котором есть модели Blog.Post и Blog.Quote. Пусть они выводятся сервером по адресу '/records.json' и в json выглядят вот так:
{posts: [{post1}, {post2}, {post3}], quotes: [{quote1}, {quote2}, {quote3}]}Что бы уменьшить количество запросов к серверу и тем самым увеличить скорость получения данных, нам нужно немного изменить datasource приложения.
Шаг 1. Создать запрос:
Blog.QUERY_POSTS_AND_QUOTES = SC.Query.local([Blog.Post, Blog.Quote]);В SC.Query.local можно передавать не только один тип записи, но и массив типов.
Шаг 2. Создать хэш-таблицу с ссылками на данные и типами записей:
Это шаг нужен что бы избежать огромного количества if в функции fetch()
Blog.Datasource = SC.DataSource.extend({
   urls: {
     posts_and_quotes: { url: '/records.json', records: ['posts', 'quotes'] }
   },
});
Так же нам нужно поправить шан запрос, установив ему атрибум id, соответствующий имени одного из элементов urls, в данном случае posts_and_quotes:
Blog.QUERY_POSTS_AND_QUOTES = SC.Query.local([Blog.Post,Blog.Quote]).set('id','posts_and_quotes');Шаг 3. Пишем fetch():
fetch: function(store, query) {
   //Получаем id запроса и берём из urls ссылку для запроса в соответствии с этим id
   var id = query.get('id');
   //Если id не задан, значит запрос не должен обращаться к серверу
   if(!id) return NO;
   var url = this.urls[id]['url'],
     funcs = this.get('fetchDidComplete'),
     //Если нужна особая обработка какого нибудь запроса то в fetchDidComplete
     //нужно добавить функцию, имя которой совпадает с id (ещё одна хэш-таблица).
     //Если имя не указано, то по завершении запроса будет вызвана default функция
     func = funcs[id] || funcs['default'];
   SC.Request.getUrl(url).json().notify(this, func, store, query).send();
   return YES;
}Шаг 4. Обрабатываем полученные данные:
fetchDidComplete: {
   'default': function(response, store, query) {
     if (SC.ok(response)) {
       //В зависимости от id берём нужные записи из полученного json
       var body = this.urls[query.get('id')]['records'];
       //Получаем тип записи
       var recordType = query.get('recordType');
       //Если тип не задан, значит их несколько и они хранятся в recordsTypes
       if (!recordType) {
       var recordTypes = query.get('recordTypes'); //Получаем типы записей
       jQuery.each(body, function(i) {
       //Загружаем в store записи разных типов. Порядок выдачи записей разных типов сервером
       //и порядок этих типов в запросе должны совпадать. Т.е.:
       //SC.Query.local[Scm.Product, Scm.Taxon] и {products: [{product1}, {product2}], taxons: [{taxon1}, {taxon2}]}
       store.loadRecords(recordTypes[i], response.get('body')[body[i]]); });
     }
     else {
       store.loadRecords(recordType, response.get('body'));
     }
     store.dataSourceDidFetchQuery(query);
     } else store.dataSourceDidErrorQuery(query, response);
   }
}Шаг 5. Используем новый запрос в приложении:
var data = Blog.store.find(Blog.QUERY_POSTS_AND_QUOTES);Теперь, что бы получить отдельно posts, а отдельно quotes используем scoped queries:
var posts = data.find(SC.Query.local(Blog.Post);
var quotes = data.find(SC.Query.local(Blog.Quote);Ну и теперь можно заполнить ArrayController'ы приложения полученными данными:
Blog.postsController.set('content', posts);
Blog.quotesController.set('content', quotes);Полностью datasource будет выглядеть так:
Blog.Datasource = SC.DataSource.extend({
urls: {
   posts_and_quotes: { url: '/records.json', records: ['posts', 'quotes'] }
},
fetch: function(store, query) {
   //Получаем id запроса и берём из urls ссылку для запроса в соответствии с этим id
   var id = query.get('id');
   //Если id не задан, значит запрос не должен обращаться к серверу
   if(!id) return NO;
   var url = this.urls[id]['url'],
     funcs = this.get('fetchDidComplete'),
     //Если нужна особая обработка какого нибудь запроса то в fetchDidComplete
     //нужно добавить функцию, имя которой совпадает с id (ещё одна хэш-таблица).
     //Если имя не указано, то по завершении запроса будет вызвана default функция
     func = funcs[id] || funcs['default'];
   SC.Request.getUrl(url).json().notify(this, func, store, query).send();
   return YES;
},
fetchDidComplete: {
   'default': function(response, store, query) {
   if (SC.ok(response)) {
     //В зависимости от id берём нужные записи из полученного json
     var body = this.urls[query.get('id')]['records'];
     //Получаем тип записи
     var recordType = query.get('recordType');
     //Если тип не задан, значит их несколько и они хранятся в recordsTypes
     if (!recordType) {
       var recordTypes = query.get('recordTypes'); //Получаем типы записей
       jQuery.each(body, function(i) {
       //Загружаем в store записи разных типов. Порядок выдачи записей разных типов сервером
       //и порядок этих типов в запросе должны совпадать. Т.е.:
       //SC.Query.local[Scm.Product, Scm.Taxon] и {products: [{product1}, {product2}], taxons: [{taxon1}, {taxon2}]}
       store.loadRecords(recordTypes[i], response.get('body')[body[i]]); });
     }
     else {
       store.loadRecords(recordType, response.get('body'));
     }
     store.dataSourceDidFetchQuery(query);
     } else store.dataSourceDidErrorQuery(query, response);
     }
   },
});
вторник, 2 августа 2011 г.
Tradefast & Sproutcore 1.6: Создание и использование тем
Tradefast & Sproutcore 1.6: Создание и использование тем
В этом небольшом руководстве описывается процесс создания и последующего использования своей темы для sproutcore-приложения, импользующего handlebars в качестве шаблонизатора.
В самом простом (и наиболее часто используемом) случае, тема - это набор css-стилей. Помимо этого темы могут заменять DOM, сгенерированный через views приложения.
Создадим новую тему командой sc-gen theme и назовём её tradefast-red:
Sproutcore добавил в /themes (если этой папки нет, то она так же будет сгенерирована) папку /tradefast_red, в которой хранятся все необходимые для темы файлы. В main.js определяется новая тема и добавляется в приложение:
По-умолчанию новая тема создаётся как под-тема темы Ace, которая не нужна, если приложение использует handlebars. Поэтому лучше удалить ‘Ace’ из определения темы:
Так же стоит убрать ace из tradefast_red/Buildfile:
Было:
Стало:
В папке /resources находятся стили вашей темы, по-умолчанию это файл theme_style.css, но вы можете добавлять сколько угодно css-файлов. В этой же папке стоит хранить все изображения, связанные с темой.
Что бы использовать тему в приложении, нужно указать её в Buildfile самого приложения, который лежит на одном уровне с папками /themes и /apps:
Обратите внимание, что имя темы совпадает с именем папки с темой в /themes/. Не перепутайте с именем, указанном в main.js. :theme => “tradefast-red” не сработает.
Остаётся только перезапустить сервер sc-server и посмотреть на новую тему в действии.
Внимание: не рекомендуется при использовании тем создавать css внутри самого приложения, так как эти стили определяются до темы и переписывают все правила, заданные в вашей теме. Вместо того что бы портить css кучей !important, лучше хранить полный css в каждой теме отдельно. Такой подход так же позволит переопределять макет приложения без лишних телодвижений.
В этом небольшом руководстве описывается процесс создания и последующего использования своей темы для sproutcore-приложения, импользующего handlebars в качестве шаблонизатора.
В самом простом (и наиболее часто используемом) случае, тема - это набор css-стилей. Помимо этого темы могут заменять DOM, сгенерированный через views приложения.
Создадим новую тему командой sc-gen theme и назовём её tradefast-red:
sc-gen theme tradefast-red
~ Created directory at themes/tradefast_red
~ Created directory at themes/tradefast_red/resources
~ Created file at themes/tradefast_red/resources/theme_styles.css
~ Created file at themes/tradefast_red/theme.js
~ Created file at themes/tradefast_red/Buildfile
Your theme is now ready to use!
Sproutcore добавил в /themes (если этой папки нет, то она так же будет сгенерирована) папку /tradefast_red, в которой хранятся все необходимые для темы файлы. В main.js определяется новая тема и добавляется в приложение:
TradefastRed = SC.AceTheme.create({
name: 'tradefast-red'
});
SC.Theme.addTheme(TradefastRed);
По-умолчанию новая тема создаётся как под-тема темы Ace, которая не нужна, если приложение использует handlebars. Поэтому лучше удалить ‘Ace’ из определения темы:
TradefastRed = SC.Theme.createТак же стоит убрать ace из tradefast_red/Buildfile:
Было:
config :tradefast_red, :css_theme => 'ace.tradefast-red'Стало:
config :tradefast_red, :css_theme => 'tradefast-red'В папке /resources находятся стили вашей темы, по-умолчанию это файл theme_style.css, но вы можете добавлять сколько угодно css-файлов. В этой же папке стоит хранить все изображения, связанные с темой.
Что бы использовать тему в приложении, нужно указать её в Buildfile самого приложения, который лежит на одном уровне с папками /themes и /apps:
config :all, :required => :sproutcore', :theme => "tradefast_red"Обратите внимание, что имя темы совпадает с именем папки с темой в /themes/. Не перепутайте с именем, указанном в main.js. :theme => “tradefast-red” не сработает.
Остаётся только перезапустить сервер sc-server и посмотреть на новую тему в действии.
Внимание: не рекомендуется при использовании тем создавать css внутри самого приложения, так как эти стили определяются до темы и переписывают все правила, заданные в вашей теме. Вместо того что бы портить css кучей !important, лучше хранить полный css в каждой теме отдельно. Такой подход так же позволит переопределять макет приложения без лишних телодвижений.
четверг, 14 июля 2011 г.
latest xen 4 and libvirt.
For connect libvirt to xen4 on fedora15 require install latest version of libvirt.
Today it is
But after tests: kvm is faster simpler and better.
Today it is
rpm -Uvh http://kojipkgs.fedoraproject.org/packages/libvirt/0.9.3/2.fc16/x86_64/libvirt-0.9.3-2.fc16.x86_64.rpm http://kojipkgs.fedoraproject.org/packages/libvirt/0.9.3/2.fc16/x86_64/libvirt-python-0.9.3-2.fc16.x86_64.rpm http://kojipkgs.fedoraproject.org/packages/libvirt/0.9.3/2.fc16/x86_64/libvirt-client-0.9.3-2.fc16.x86_64.rpm http://kojipkgs.fedoraproject.org/packages/parted/3.0/2.fc16/x86_64/parted-3.0-2.fc16.x86_64.rpm http://kojipkgs.fedoraproject.org/packages/netcf/0.1.8/1.fc16/x86_64/netcf-libs-0.1.8-1.fc16.x86_64.rpm But after tests: kvm is faster simpler and better.
воскресенье, 10 июля 2011 г.
capybara get html
For get html
for get elements count
find("ul.random_quotes").native.to_htmlfor get elements count
find("ul.random_quotes").native.search("li").size
Подписаться на:
Сообщения (Atom)