Friday, September 30, 2005

mnoGoSearch Alias

วันก่อนพูดถึง mnoGoSearch ไป
จุดประสงค์ที่ทดลองใช้ mnoGoSearch ก็เพื่อที่จะนำไปทำ
search engine สำหรับ
Code Snippet Application ที่เขียนขึ้นมา

ซึ่ง Feature ที่ดี mnoGoSearch อย่างหนึ่ง
ก็คือสามารถ access เข้า database
เพื่อทำ index จาก Database table ได้โดยตรง
Feature นี้ mnoGoSearch ตั้งชื่อ protocol ว่า htdb

ปัญหาที่เจอก็คือ เมื่อเราใช้ front-end tool
ของ mnogoSearch ค้นหาข้อมูล
ผลลัพท์ที่ได้ จะแสดงในรูป
htdb:/xx
โดย xx คือ primary key ของ table ที่ทำ index



ซึ่งในกรณีที่เราใช้ program ด้วยกันเป็นคน search
ก็คงไม่มีปัญหาอะไร เพราะสามารถตัดต่อ string
เพื่อนำไปสร้าง url ที่เหมาะสมได้

สำหรับกรณีที่เราต้องการให้ front-end tool ของ mnogosearch
สามารถแสดงผลเป็น url ที่สามารถ click ได้จริงๆ
ก็สามารถทำได้โดย
เข้าไปแก้ไข template file ที่ชื่อ search.htm
(เก็บอยู่ใน /usr/local/mnogosearch/etc)
เพิ่มคำสั่ง
Alias htdb:/ http://localhost/snn/snippets/show/

เท่านี้ mnoGoSearch ก็จะทำการ rewrite ผลลัพท์ให้เราใหม่

Related link from Roti

Config fastcgi ให้กับ rails

ช่วงนี้จะใช้ Snippets Application ที่เขียนขึ้นเองแล้ว
ก็เลยจะ deploy ให้เหมือนกันสถานการณ์การทำงานจริง



ปกติใน rails เราสามารถ run application ได้ 3 แบบหลักๆ คือ
  • ผ่านทาง WebBrick
    เจ้า WebBrick เป็น web server ที่เขียนด้วย Ruby
    เป็นสภาพแวดล้อมที่เหมาะสมอย่างยิ่งกับการ debug
  • ผ่านทาง Apache CGI
    อันนี้จะช้าหน่อย แต่เหมาะแก่การ test deploy ครั้งแรก
    เพราะจะได้ check พวก configuration, permission
    ให้ถูกต้องก่อน
  • ผ่านทาง Apache + mod_fastcgi


ที่เราจะทดลองก็คือ ใช้ FastCGI

เริ่มแรก ก็ต้อง install mod_fastcgi ก่อน
ขั้นนี้ไม่ยุ่งยากอะไร ก็แค่ download source code มา แล้วก็ build

จากนั้นก็ install fcgi developer kit
(ruby fcgi ต้องการใช้)

สุดท้ายก็ install ruby-fcgi

ส่วนการ deploy rails application
ถ้าอย่างง่าย ก็เพียงแต่ทำ link จาก htdocs
ไปยัง directory project/public

จากนั้นก็ config Directory ที่เราทำ link ไว้
โดย enable ให้สามารถ run cgi ได้
<Directory "/Library/WebServer/Documents/snn">
Options +ExecCGI FollowSymLinks
AllowOverride all
Allow from all
Order allow,deny
</Directory>


จากนั้นก็เข้าไปแก้ไข file .htaccess ที่อยู่ใน directory project/public
(file นี้ rails generate ให้เราอัตโนมัติ)
แก้ไข ส่วน rewrite rule จากของเดิมที่ใช้ dispatch.cgi
ไปเป็น dispatch.fcgi แทน

ปรับส่วน rewrite rule ให้เหมาะสมกับ structure ใหม่ของเราด้วย
(ขั้นนี้แหล่ะที่ค่อนข้างมั่ว เพราะเจ้า apache rewrite มันช่าง
เข้าใจยากจริงๆ)

เข้าไปแก้ไข projectdir/public/dispatch.fcgi
ระบุ directory ของ log file ที่ต้องการ
RailsFCGIHandler.process! '/tmp/snippet_fcgi_crash.log'


เมื่อเราเรียกใช้ครั้งแรกสุด apache จะ start process dispatch.fcgi ให้อัตโนมัติ
แต่บางทีเราต้องการให้ start process ขึ้นมารอเลย
(เพื่อไม่ให้เกิดอาการ lag เมื่อ user เริ่มเข้ามาใช้)
ในกรณีนี้ ก็ให้เพิ่ม directive นี้เข้าไปใน httpd.conf
<IfModule mod_fastcgi.c>
FastCgiIpcDir /tmp/fcgi_ipc
FastCgiServer /Library/WebServer/Documents/snn/dispatch.fcgi \
-initial-env RAILS_ENV=production -processes 15 -idle-timeout 60
</IfModule>

Related link from Roti

ทดลอง mnoGoSearch

วันนี้อ่านเจอใน Planet Eclipse ว่า
site eclipse.org จะปรับปรุง search engine ใหม่
โดยจะปรับปรุงกฎการให้น้ำหนัก
ที่น่าสนใจก็คือ เขาบอกด้วยว่า เขาใช้ mnoGoSearch เป็น search engine
ก็เลยตามไปดูสักหน่อย

ตัว mnoGoSearch เป็น search engine ที่ใช้ database table
ในการทำ index (lucene ใช้ file system)
ตัวมันประกอบด้วย 2 ส่วนคือ
  • Indexer ที่ใช้ scan web document เพื่อทำ index
  • CGI front-end ที่ใช้ในการ search


ที่น่าสนใจ ก็คือ mnoGoSearch support ภาษาไทย ด้วย
โดยมี dictionary thai มาให้ด้วย โดยมีจำนวนศัพท์มาให้ 32895 คำ

ในขั้นตอนการทำ index เราสามารถ config
ให้มัน scan web site ได้หลายลักษณะ เช่น

  • page scan เฉพาะ page ที่ระบุ
  • path scan เฉพาะ document ที่อยู่ใต้ path ที่ระบุ
  • site scan documents ที่อยู่ใน host นั้น
  • world scan any document



ตัวอย่างเช่น

# To index whole server "localhost":
Server http://localhost/
#
# You can also specify some path to index subdirectory only:
Server http://localhost/subdir/
#
# To specify the only one page:
Server page http://localhost/path/main.html


ผมไม่ค่อยสนใจ feature ที่ใช้ scan static web site เท่าไร
ที่สนใจก็คือ feature ที่สามารถใช้ scan database table ได้โดยตรงมากกว่า
ตัว mnoGoSearch มี protocol ที่เรียกว่า HTDB สำหรับทำแบบนี้

ลักษณะการทำงาน เป็นดังนี้
  • ระบุ connection ที่จะใช้ต่อ database (dbname, user, password)
  • select primary key ของ table ที่เราต้องการ scan ขึ้นมาทั้งหมด
  • กำหนด select ที่ทำให้ได้เนื้อหาของข้อมูลที่เราต้องการทำ index


ลองดูตัวอย่าง

HTDBAddr mysql://user:passwd@localhost/dbname/?dbmode=single

เริ่มด้วยการระบุ database


HTDBList "select id from snippets"

ในที่นี้เราต้องการทำ index บน table snippets


HTDBDoc "select concat('HTTP/1.0 200 OK\\r\\n', 'Content-type: text/plain;charset=utf-8\\r\\n', 'Content-Language: th\\r\\n','\\r\\n', description) from snippets where id = $1 "

จากนั้นก็ระบุ sql ที่ทำให้ได้เนื้อหาที่ต้องการทำ index
โดย mnoGoSearch จะ pass primary key เข้ามาให้
ในชื่อตัวแปร $1

จะเห็นได้ว่าเราต้องแปลงเนื้อหาของเรา
ให้อยู่ในรูปแบบของ http response เสียก่อน
key ที่สำคัญตัวที่หนึ่งก็คือ การระบุ language
ไม่งั้นมันจะพยายามเดา language ให้เอง
ส่วนตัวที่ 2 ก็คือการระบุ encoding ที่ใช้


ส่วนรูปข้างล่างนี้เป็น screen dump หน้าจอ search ของ mnoGoSearch



จะเห็นได้ว่า ผลลัพท์ที่เราได้จะมี url ในรูปของ htdb:/nn
ตัวเลข nn ก็คือ primary key ของ row ที่ search เจอนั่นเอง

ในส่วนของการ scan static web site นั้น
เท่าที่ลองใช้ดู ทดลอง scan 2 ที่นี้ดู

Server page http://www.pantip.com/cafe/index.html
Server page http://bact.blogspot.com/2005/09/web-20-office.html




ของ pantip ทำ index ออกมาได้ ทดลองค้นหาดู
พบว่าคำบางคำ ก็ค้นเจอ บางคำก็ไม่เจอ
เช่น ถ้าใช้คำว่า"ห้องสมุด" จะเจอ ส่วนคำว่า "ไกล", "ไกลบ้าน"
นั้นหาไม่เจอ แต่ถ้าเปลี่ยนเป็น "บ้าน" เฉยๆ ก็จะเจอ



ส่วนของ bact จะเห็นว่าอ่านภาษาไทยมาถูกต้อง
แต่ search ด้วยภาษาไทยไม่เจอเลย
ไปดูใน datadict ของ mnoGoSearch มันระบุว่า
site นี้ Content-Language เป็น ภาษาอังกฤษ (en)
ก็เป็นไปได้ว่ามันเดาภาษาผิด ก็เลยไม่ได้เอา dict ไทยไปจับ

Related link from Roti

Wednesday, September 28, 2005

The Wall of DEATH

เอามาจาก blog The Fishbowl
เขาพูดถึงวิธีการที่จะช่วยให้ developer focus งานที่ต้องทำ

ชอบตรง
The rules of the wall are:
1. Developers take an issue off the wall, and work on it until it is done
2. Developers must not work on anything that is not on the wall
3. Corollary to rule 2: unanticipated additional work must be filed in JIRA, then written on a card and placed on the wall
4. Developers must never take more than one issue off the wall at a time
5. Once an issue is done, the developer records the actual time taken in the other corner of the issue, dumps it in the ‘done’ pile, and updates the whiteboard.
6. Repeat until no issues remain on the wall


มันจับต้องได้ดี
ไว้โปรเจคหน้าจะเตรียมผนังไว้บ้าง

Related link from Roti

Monday, September 26, 2005

ทดลอง send message จาก ruby ไป java ผ่าน Stomp Protocol

วันนี้ทดลองใช้ ActiveMQ เป็นตัวกลางในการ communicate
ระหว่าง Java กับ Ruby

ในส่วนของ Java ผมใช้ jencks ซึ่งเป็น lightweight container
ที่สามารถ deploy ใน Spring ได้ ตัว jencks ทำให้เรา run
Message Bean นอก j2ee server ได้

ตัว Message Bean ทดลองเขียนดังนี้
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class EchoBean implements MessageListener {

public void onMessage(Message msg) {
try {
System.out.println("i got message");
TextMessage txt = (TextMessage) msg;
System.out.println(txt.getText());
} catch (JMSException je) {
je.printStackTrace();
}
}
}


ส่วนของ Spring Application Config file นี้ยุ่งขึ้นมาหน่อย
เขียนดังนี้

เริ่มด้วยการ add jencks ก่อน
<bean id="jencks" class="org.jencks.JCAContainer">
<property name="bootstrapContext">
<bean class="org.jencks.factory.BootstrapContextFactoryBean">
<property name="threadPoolSize" value="25"/>
</bean>
</property>

<property name="resourceAdapter">
<bean id="activeMQResourceAdapter" class="org.activemq.ra.ActiveMQResour
ceAdapter">
<property name="serverUrl" value="tcp://localhost:61616"/>
</bean>
</property>
</bean>


จากนั้นก็ใส่ EchoBean ที่เราเขียนเข้าไป
<bean id="monitor" factory-method="addConnector" factory-bean="jencks" singleton
="true">
<property name="activationSpec">
<bean class="org.activemq.ra.ActiveMQActivationSpec">
<property name="destination" value="Monitor.Queue"/>
<property name="destinationType" value="javax.jms.Queue"/>
</bean>
</property>

<property name="ref" value="echoBean"/>
</bean>

<bean id="echoBean" class="mx.test.mq.EchoBean" singleton="true"/>


เท่านี้ก็เรียบร้อย เวลา run ก็เพียงแต่ load Application Context
ClassPathXmlApplicationContext appContext = 
new ClassPathXmlApplicationContext(
new String[] {"beans.xml"});


ก่อนที่จะเขียนส่วน Ruby Client
เราต้อง config ActiveMQ ให้เปิด port ที่รับ Stomp protocol เสียก่อน
ซึ่งทำได้โดย เข้าไปแก้ activemq.xml
เพิ่มบรรทัดนี้เข้าไป
<connector>
<serverTransport uri="stomp://localhost:61626"/>
</connector>


ทีนี้มาว่าด้วยส่วน ruby บ้าง
ตัว api ที่ใช้ interface กับ Stomp สามารถ download ได้ที่นี่ Link
วิธีการใช้งานทำได้ดังนี้

เริ่มต้นด้วยการ open connection กับ ActiveMQ ก่อน
conn = Stomp::Connection.open('user','pass','localh',port)


ในกรณีที่ต้องการส่ง Message ก็เพียงแต่
conn.send('/queue/test', 'hello');

Note: เราต้องระบุชนิดของ destination เสมอ
โดยการระบุ prefix ที่จะต้องขึ้นต้นด้วย /queue/ หรือ /topic/


กรณีที่ต้องการส่งหลายๆ message และให้มี transaction control ด้วย
ก็เพียงแต่ใส่ begin, commit ครอบลงไป
conn.begin
conn.send('/queue/test', 'hello');
conn.send('/topic/test', 'hello');
conn.commit


ส่วนกรณีที่ต้องการรับ Message
ก็ให้ subscribe เข้ากับ Topic หรือ Queue ที่ต้องการ
conn.subscribe('/queue/test') { |msg| 
puts msg.body
}

Related link from Roti